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 Jun 06 Brian Frank Creation
7 //
8
9 **
10 ** CType is a "compiler type" which is class used for representing
11 ** the Fan type system in the compiler. CTypes map to types within
12 ** the compilation units themsevles as TypeDef and TypeRef or to
13 ** precompiled types in imported pods via ReflectType or FType.
14 **
15 mixin CType
16 {
17
18 //////////////////////////////////////////////////////////////////////////
19 // Naming
20 //////////////////////////////////////////////////////////////////////////
21
22 **
23 ** Associated namespace for this type representation
24 **
25 abstract Namespace ns()
26
27 **
28 ** Parent pod which defines this type.
29 **
30 abstract CPod pod()
31
32 **
33 ** Simple name of the type such as "Str".
34 **
35 abstract Str name()
36
37 **
38 ** Qualified name such as "sys:Str".
39 **
40 abstract Str qname()
41
42 **
43 ** This is the full signature of the type.
44 **
45 abstract Str signature()
46
47 **
48 ** If this is a TypeRef, return what it references
49 **
50 virtual CType deref() { return this }
51
52 //////////////////////////////////////////////////////////////////////////
53 // Generics
54 //////////////////////////////////////////////////////////////////////////
55
56 **
57 ** A generic type means that one or more of my slots contain signatures
58 ** using a generic parameter (such as V or K). Fan supports three built-in
59 ** generic types: List, Map, and Func. A generic instance (such as Str[])
60 ** is NOT a generic type (all of its generic parameters have been filled in).
61 ** User defined generic types are not supported in Fan.
62 **
63 abstract Bool isGeneric()
64
65 **
66 ** A parameterized type is a type which has parameterized a generic type
67 ** and replaced all the generic parameter types with generic argument
68 ** types. The type Str[] is a parameterized type of the generic type
69 ** List (V is replaced with Str). A parameterized type always has a
70 ** signature which is different from the qname.
71 **
72 abstract Bool isParameterized()
73
74 **
75 ** Return if this type is a generic parameter (such as V or K) in a
76 ** generic type (List, Map, or Method). Generic parameters serve
77 ** as place holders for the parameterization of the generic type.
78 ** Fan has a predefined set of generic parameters which are always
79 ** defined in the sys pod with a one character name.
80 **
81 abstract Bool isGenericParameter()
82
83 **
84 ** Create a parameterized List of this type.
85 **
86 abstract ListType toListOf()
87
88 **
89 ** If this type is a generic parameter (V, L, etc), then return
90 ** the actual type for the native implementation. For example V
91 ** is Obj, and L is List. This is the type we actually use when
92 ** constructing a signature for the invoke opcode.
93 **
94 CType raw()
95 {
96 // if not generic parameter, always use this type
97 if (!isGenericParameter) return this
98
99 // it's possible that this type is a generic unparameterized
100 // instance of Method (such as List.each), in which case
101 // we should use this type itself
102 if (name.size != 1) return this
103
104 switch (name[0])
105 {
106 case 'L': return ns.listType
107 case 'M': return ns.mapType
108 default: return ns.objType
109 }
110 }
111
112 //////////////////////////////////////////////////////////////////////////
113 // Inheritance
114 //////////////////////////////////////////////////////////////////////////
115
116 **
117 ** The direct super class of this type (null for Obj).
118 **
119 abstract CType base()
120
121 **
122 ** Return the mixins directly implemented by this type.
123 **
124 abstract CType[] mixins()
125
126 **
127 ** Hash on signature.
128 **
129 override Int hash()
130 {
131 return signature.hash
132 }
133
134 **
135 ** Equality based on signature.
136 **
137 override Bool equals(Obj t)
138 {
139 if (this === t) return true
140 that := t as CType
141 if (that == null) return false
142 return signature == that.signature
143 }
144
145 **
146 ** Does this type implement the specified type. If true, then
147 ** this type is assignable to the specified type (although the
148 ** converse is not necessarily true). All types (including
149 ** mixin types) fit sys::Obj.
150 **
151 virtual Bool fits(CType t)
152 {
153 // short circuit if myself
154 if (this == t) return true
155
156 // recurse extends
157 if (base != null && base.fits(t)) return true
158
159 // recuse mixins
160 for (i:=0; i<mixins.size; ++i)
161 if (mixins[i].fits(t)) return true
162
163 // let anything fit unparameterized generic parameters like
164 // V, K (in case we are using List, Map, or Method directly)
165 if (t.name.size == 1 && t.pod.name == "sys")
166 return true
167
168 // no fit
169 return false
170 }
171
172 **
173 ** Return if this type fits any of the types in the specified list.
174 **
175 Bool fitsAny(CType[] types)
176 {
177 return types.any |CType t->Bool| { return this.fits(t) }
178 }
179
180 **
181 ** Given a list of types, compute the most specific type which they
182 ** all share, or at worst return sys::Obj. This method does not take
183 ** into account mixins, only extends class inheritance.
184 **
185 public static CType common(Namespace ns, CType[] types)
186 {
187 if (types.isEmpty) return ns.objType
188 best := types[0]
189 for (Int i:=1; i<types.size; ++i)
190 {
191 t := types[i]
192 while (!t.fits(best))
193 {
194 best = best.base
195 if (best == null) return ns.objType
196 }
197 }
198 return best
199 }
200
201 //////////////////////////////////////////////////////////////////////////
202 // Flags
203 //////////////////////////////////////////////////////////////////////////
204
205 **
206 ** Get the flags bitmask.
207 **
208 abstract Int flags()
209
210 **
211 ** Return if this Type is a class (as opposed to enum or mixin)
212 **
213 Bool isClass() { return !isMixin && !isEnum }
214
215 **
216 ** Return if this Type is a mixin type and cannot be instantiated.
217 **
218 Bool isMixin() { return flags & FConst.Mixin != 0 }
219
220 **
221 ** Return if this Type is an sys::Enum
222 **
223 Bool isEnum() { return flags & FConst.Enum != 0 }
224
225 **
226 ** Return if this Type is abstract and cannot be instantiated. This
227 ** method will always return true if the type is a mixin.
228 **
229 Bool isAbstract() { return flags & FConst.Abstract != 0 }
230
231 **
232 ** Return if this Type is const and immutable.
233 **
234 Bool isConst() { return flags & FConst.Const != 0 }
235
236 **
237 ** Return if this Type is final and cannot be subclassed.
238 **
239 Bool isFinal() { return flags & FConst.Final != 0 }
240
241 **
242 ** Is this a public scoped class
243 **
244 Bool isPublic() { return flags & FConst.Public != 0 }
245
246 **
247 ** Is this an internally scoped class
248 **
249 Bool isInternal() { return flags & FConst.Internal != 0 }
250
251 **
252 ** Is this a compiler generated synthetic class
253 **
254 Bool isSynthetic() { return flags & FConst.Synthetic != 0 }
255
256 //////////////////////////////////////////////////////////////////////////
257 // Conveniences
258 //////////////////////////////////////////////////////////////////////////
259
260 Bool isObj() { return qname == "sys::Obj" }
261 Bool isBool() { return qname == "sys::Bool" }
262 Bool isInt() { return qname == "sys::Int" }
263 Bool isFloat() { return qname == "sys::Float" }
264 Bool isRange() { return qname == "sys::Range" }
265 Bool isStr() { return qname == "sys::Str" }
266 Bool isType() { return qname == "sys::Type" }
267 Bool isVoid() { return qname == "sys::Void" }
268
269 //////////////////////////////////////////////////////////////////////////
270 // Slots
271 //////////////////////////////////////////////////////////////////////////
272
273 **
274 ** Map of the all defined slots, both fields and
275 ** methods (including inherited slots).
276 **
277 abstract Str:CSlot slots()
278
279 **
280 ** Return if this type contains a slot by the specified name.
281 **
282 Bool hasSlot(Str name) { return slots.containsKey(name) }
283
284 **
285 ** Lookup a slot by name. If the slot doesn't exist then return null.
286 **
287 virtual CSlot slot(Str name) { return slots[name] }
288
289 **
290 ** Lookup a field by name.
291 **
292 CField field(Str name) { return (CField)slot(name) }
293
294 **
295 ** Lookup a method by name.
296 **
297 CMethod method(Str name) { return (CMethod)slot(name) }
298
299 **
300 ** List of the all defined fields (including inherited fields).
301 **
302 CField[] fields() { return (CField[])slots.values.findType(CField.type) }
303
304 **
305 ** List of the all defined methods (including inherited methods).
306 **
307 CMethod[] methods() { return (CMethod[])slots.values.findType(CMethod.type) }
308
309 **
310 ** List of the all constructors.
311 **
312 CMethod[] ctors() { return methods.findAll |CMethod m->Bool| { return m.isCtor } }
313
314 }
2 // Copyright (c) 2006, Brian Frank and Andy Frank
3 // Licensed under the Academic Free License version 3.0
4 //
5 // History:
6 // 4 Jun 06 Brian Frank Creation
7 //
8
9 **
10 ** CType is a "compiler type" which is class used for representing
11 ** the Fan type system in the compiler. CTypes map to types within
12 ** the compilation units themsevles as TypeDef and TypeRef or to
13 ** precompiled types in imported pods via ReflectType or FType.
14 **
15 mixin CType
16 {
17
18 //////////////////////////////////////////////////////////////////////////
19 // Naming
20 //////////////////////////////////////////////////////////////////////////
21
22 **
23 ** Associated namespace for this type representation
24 **
25 abstract Namespace ns()
26
27 **
28 ** Parent pod which defines this type.
29 **
30 abstract CPod pod()
31
32 **
33 ** Simple name of the type such as "Str".
34 **
35 abstract Str name()
36
37 **
38 ** Qualified name such as "sys:Str".
39 **
40 abstract Str qname()
41
42 **
43 ** This is the full signature of the type.
44 **
45 abstract Str signature()
46
47 **
48 ** If this is a TypeRef, return what it references
49 **
50 virtual CType deref() { return this }
51
52 //////////////////////////////////////////////////////////////////////////
53 // Generics
54 //////////////////////////////////////////////////////////////////////////
55
56 **
57 ** A generic type means that one or more of my slots contain signatures
58 ** using a generic parameter (such as V or K). Fan supports three built-in
59 ** generic types: List, Map, and Func. A generic instance (such as Str[])
60 ** is NOT a generic type (all of its generic parameters have been filled in).
61 ** User defined generic types are not supported in Fan.
62 **
63 abstract Bool isGeneric()
64
65 **
66 ** A parameterized type is a type which has parameterized a generic type
67 ** and replaced all the generic parameter types with generic argument
68 ** types. The type Str[] is a parameterized type of the generic type
69 ** List (V is replaced with Str). A parameterized type always has a
70 ** signature which is different from the qname.
71 **
72 abstract Bool isParameterized()
73
74 **
75 ** Return if this type is a generic parameter (such as V or K) in a
76 ** generic type (List, Map, or Method). Generic parameters serve
77 ** as place holders for the parameterization of the generic type.
78 ** Fan has a predefined set of generic parameters which are always
79 ** defined in the sys pod with a one character name.
80 **
81 abstract Bool isGenericParameter()
82
83 **
84 ** Create a parameterized List of this type.
85 **
86 abstract ListType toListOf()
87
88 **
89 ** If this type is a generic parameter (V, L, etc), then return
90 ** the actual type for the native implementation. For example V
91 ** is Obj, and L is List. This is the type we actually use when
92 ** constructing a signature for the invoke opcode.
93 **
94 CType raw()
95 {
96 // if not generic parameter, always use this type
97 if (!isGenericParameter) return this
98
99 // it's possible that this type is a generic unparameterized
100 // instance of Method (such as List.each), in which case
101 // we should use this type itself
102 if (name.size != 1) return this
103
104 switch (name[0])
105 {
106 case 'L': return ns.listType
107 case 'M': return ns.mapType
108 default: return ns.objType
109 }
110 }
111
112 //////////////////////////////////////////////////////////////////////////
113 // Inheritance
114 //////////////////////////////////////////////////////////////////////////
115
116 **
117 ** The direct super class of this type (null for Obj).
118 **
119 abstract CType base()
120
121 **
122 ** Return the mixins directly implemented by this type.
123 **
124 abstract CType[] mixins()
125
126 **
127 ** Hash on signature.
128 **
129 override Int hash()
130 {
131 return signature.hash
132 }
133
134 **
135 ** Equality based on signature.
136 **
137 override Bool equals(Obj t)
138 {
139 if (this === t) return true
140 that := t as CType
141 if (that == null) return false
142 return signature == that.signature
143 }
144
145 **
146 ** Does this type implement the specified type. If true, then
147 ** this type is assignable to the specified type (although the
148 ** converse is not necessarily true). All types (including
149 ** mixin types) fit sys::Obj.
150 **
151 virtual Bool fits(CType t)
152 {
153 // short circuit if myself
154 if (this == t) return true
155
156 // recurse extends
157 if (base != null && base.fits(t)) return true
158
159 // recuse mixins
160 for (i:=0; i<mixins.size; ++i)
161 if (mixins[i].fits(t)) return true
162
163 // let anything fit unparameterized generic parameters like
164 // V, K (in case we are using List, Map, or Method directly)
165 if (t.name.size == 1 && t.pod.name == "sys")
166 return true
167
168 // no fit
169 return false
170 }
171
172 **
173 ** Return if this type fits any of the types in the specified list.
174 **
175 Bool fitsAny(CType[] types)
176 {
177 return types.any |CType t->Bool| { return this.fits(t) }
178 }
179
180 **
181 ** Given a list of types, compute the most specific type which they
182 ** all share, or at worst return sys::Obj. This method does not take
183 ** into account mixins, only extends class inheritance.
184 **
185 public static CType common(Namespace ns, CType[] types)
186 {
187 if (types.isEmpty) return ns.objType
188 best := types[0]
189 for (Int i:=1; i<types.size; ++i)
190 {
191 t := types[i]
192 while (!t.fits(best))
193 {
194 best = best.base
195 if (best == null) return ns.objType
196 }
197 }
198 return best
199 }
200
201 //////////////////////////////////////////////////////////////////////////
202 // Flags
203 //////////////////////////////////////////////////////////////////////////
204
205 **
206 ** Get the flags bitmask.
207 **
208 abstract Int flags()
209
210 **
211 ** Return if this Type is a class (as opposed to enum or mixin)
212 **
213 Bool isClass() { return !isMixin && !isEnum }
214
215 **
216 ** Return if this Type is a mixin type and cannot be instantiated.
217 **
218 Bool isMixin() { return flags & FConst.Mixin != 0 }
219
220 **
221 ** Return if this Type is an sys::Enum
222 **
223 Bool isEnum() { return flags & FConst.Enum != 0 }
224
225 **
226 ** Return if this Type is abstract and cannot be instantiated. This
227 ** method will always return true if the type is a mixin.
228 **
229 Bool isAbstract() { return flags & FConst.Abstract != 0 }
230
231 **
232 ** Return if this Type is const and immutable.
233 **
234 Bool isConst() { return flags & FConst.Const != 0 }
235
236 **
237 ** Return if this Type is final and cannot be subclassed.
238 **
239 Bool isFinal() { return flags & FConst.Final != 0 }
240
241 **
242 ** Is this a public scoped class
243 **
244 Bool isPublic() { return flags & FConst.Public != 0 }
245
246 **
247 ** Is this an internally scoped class
248 **
249 Bool isInternal() { return flags & FConst.Internal != 0 }
250
251 **
252 ** Is this a compiler generated synthetic class
253 **
254 Bool isSynthetic() { return flags & FConst.Synthetic != 0 }
255
256 //////////////////////////////////////////////////////////////////////////
257 // Conveniences
258 //////////////////////////////////////////////////////////////////////////
259
260 Bool isObj() { return qname == "sys::Obj" }
261 Bool isBool() { return qname == "sys::Bool" }
262 Bool isInt() { return qname == "sys::Int" }
263 Bool isFloat() { return qname == "sys::Float" }
264 Bool isRange() { return qname == "sys::Range" }
265 Bool isStr() { return qname == "sys::Str" }
266 Bool isType() { return qname == "sys::Type" }
267 Bool isVoid() { return qname == "sys::Void" }
268
269 //////////////////////////////////////////////////////////////////////////
270 // Slots
271 //////////////////////////////////////////////////////////////////////////
272
273 **
274 ** Map of the all defined slots, both fields and
275 ** methods (including inherited slots).
276 **
277 abstract Str:CSlot slots()
278
279 **
280 ** Return if this type contains a slot by the specified name.
281 **
282 Bool hasSlot(Str name) { return slots.containsKey(name) }
283
284 **
285 ** Lookup a slot by name. If the slot doesn't exist then return null.
286 **
287 virtual CSlot slot(Str name) { return slots[name] }
288
289 **
290 ** Lookup a field by name.
291 **
292 CField field(Str name) { return (CField)slot(name) }
293
294 **
295 ** Lookup a method by name.
296 **
297 CMethod method(Str name) { return (CMethod)slot(name) }
298
299 **
300 ** List of the all defined fields (including inherited fields).
301 **
302 CField[] fields() { return (CField[])slots.values.findType(CField.type) }
303
304 **
305 ** List of the all defined methods (including inherited methods).
306 **
307 CMethod[] methods() { return (CMethod[])slots.values.findType(CMethod.type) }
308
309 **
310 ** List of the all constructors.
311 **
312 CMethod[] ctors() { return methods.findAll |CMethod m->Bool| { return m.isCtor } }
313
314 }
More Info
Slots
- base
- common
- ctors
- deref
- equals
- field
- fields
- fits
- fitsAny
- flags
- hasSlot
- hash
- isAbstract
- isBool
- isClass
- isConst
- isEnum
- isFinal
- isFloat
- isGeneric
- isGenericParameter
- isInt
- isInternal
- isMixin
- isObj
- isParameterized
- isPublic
- isRange
- isStr
- isSynthetic
- isType
- isVoid
- method
- methods
- mixins
- name
- ns
- pod
- qname
- raw
- signature
- slot
- slots
- toListOf