BOO-999
[boo.git] / src / Boo.Lang.Compiler / TypeSystem / AbstractInternalType.cs
blob5c8d51be40ed735ad157d3d59542909273805b93
1 #region license
2 // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright notice,
11 // this list of conditions and the following disclaimer in the documentation
12 // and/or other materials provided with the distribution.
13 // * Neither the name of Rodrigo B. de Oliveira nor the names of its
14 // contributors may be used to endorse or promote products derived from this
15 // software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
21 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #endregion
29 namespace Boo.Lang.Compiler.TypeSystem
31 using System;
32 using System.Collections;
33 using System.Reflection;
34 using Boo.Lang.Compiler.Ast;
35 using Attribute = Boo.Lang.Compiler.Ast.Attribute;
36 using System.Collections.Generic;
38 public abstract class AbstractInternalType : IInternalEntity, IType, INamespace, IGenericTypeInfo
40 public static readonly IConstructor[] NoConstructors = new IConstructor[0];
42 protected TypeSystemServices _typeSystemServices;
44 protected TypeDefinition _typeDefinition;
46 protected INamespace _parentNamespace;
48 private string _fullName = null;
50 private IGenericParameter[] _genericParameters = null;
52 private Dictionary<IType[], IType> _constructedTypes = new Dictionary<IType[], IType>(ArrayEqualityComparer<IType>.Default);
54 protected AbstractInternalType(TypeSystemServices typeSystemServices, TypeDefinition typeDefinition)
56 _typeSystemServices = typeSystemServices;
57 _typeDefinition = typeDefinition;
60 protected virtual string BuildFullName()
62 string fullName = _typeDefinition.FullName;
64 if (GenericInfo != null)
66 fullName = string.Format("{0}`{1}", fullName, GenericInfo.GenericParameters.Length);
69 return fullName;
72 public string FullName
74 get { return _fullName ?? (_fullName = BuildFullName()); }
77 public string Name
79 get
81 return _typeDefinition.Name;
85 public Node Node
87 get
89 return _typeDefinition;
93 public IType NestingType
95 get
97 return _typeDefinition.ParentNode.Entity as IType;
101 public virtual INamespace ParentNamespace
105 if (null == _parentNamespace)
107 _parentNamespace = (INamespace)TypeSystemServices.GetEntity(_typeDefinition.ParentNode);
109 return _parentNamespace;
113 public virtual bool Resolve(List targetList, string name, EntityType flags)
115 bool found = false;
117 // Try to resolve name as a generic parameter
118 if (NameResolutionService.IsFlagSet(flags, EntityType.Type))
120 foreach (GenericParameterDeclaration gpd in _typeDefinition.GenericParameters)
122 if (gpd.Name == name)
124 targetList.AddUnique(gpd.Entity);
125 return true;
130 // Try to resolve name as a member
131 foreach (IEntity entity in GetMembers())
133 if (entity.Name == name && NameResolutionService.IsFlagSet(flags, entity.EntityType))
135 targetList.AddUnique(entity);
136 found = true;
140 return found;
143 public virtual IType BaseType
147 return null;
151 public TypeDefinition TypeDefinition
155 return _typeDefinition;
159 public IType Type
163 return this;
167 public bool IsByRef
171 return false;
175 public IType GetElementType()
177 return null;
180 public bool IsClass
184 return NodeType.ClassDefinition == _typeDefinition.NodeType;
188 public bool IsAbstract
192 return _typeDefinition.IsAbstract;
196 virtual public bool IsFinal
200 return _typeDefinition.IsFinal || IsValueType;
204 public bool IsInterface
208 return NodeType.InterfaceDefinition == _typeDefinition.NodeType;
212 public bool IsEnum
216 return NodeType.EnumDefinition == _typeDefinition.NodeType;
220 virtual public bool IsValueType
224 return false;
228 public bool IsArray
232 return false;
236 public virtual int GetTypeDepth()
238 return 1;
241 public IEntity GetDefaultMember()
243 IType defaultMemberAttribute = _typeSystemServices.Map(Types.DefaultMemberAttribute);
244 foreach (Attribute attribute in _typeDefinition.Attributes)
246 IConstructor tag = TypeSystemServices.GetEntity(attribute) as IConstructor;
247 if (null != tag)
249 if (defaultMemberAttribute == tag.DeclaringType)
251 StringLiteralExpression memberName = attribute.Arguments[0] as StringLiteralExpression;
252 if (null != memberName)
254 List buffer = new List();
255 Resolve(buffer, memberName.Value, EntityType.Any);
256 return NameResolutionService.GetEntityFromList(buffer);
261 if (_typeDefinition.BaseTypes.Count > 0)
263 List buffer = new List();
265 foreach (TypeReference baseType in _typeDefinition.BaseTypes)
267 IType tag = TypeSystemServices.GetType(baseType);
268 IEntity defaultMember = tag.GetDefaultMember();
269 if (defaultMember != null)
271 if (tag.IsInterface)
273 buffer.AddUnique(defaultMember);
275 else //non-interface base class trumps interfaces
277 return defaultMember;
281 return NameResolutionService.GetEntityFromList(buffer);
283 return null;
286 public virtual EntityType EntityType
290 return EntityType.Type;
294 public virtual bool IsSubclassOf(IType other)
296 return false;
299 public virtual bool IsAssignableFrom(IType other)
301 return this == other ||
302 (!this.IsValueType && Null.Default == other) ||
303 other.IsSubclassOf(this);
306 public virtual IConstructor[] GetConstructors()
308 return NoConstructors;
311 public IType[] GetInterfaces()
313 List buffer = new List(_typeDefinition.BaseTypes.Count);
314 foreach (TypeReference baseType in _typeDefinition.BaseTypes)
316 IType type = TypeSystemServices.GetType(baseType);
317 if (type.IsInterface) buffer.AddUnique(type);
319 return (IType[])buffer.ToArray(new IType[buffer.Count]);
322 public virtual IEntity[] GetMembers()
324 return GetMemberEntities(_typeDefinition.Members);
327 private IEntity[] GetMemberEntities(TypeMemberCollection members)
329 IEntity[] entities = new IEntity[members.Count];
330 for (int i = 0; i < entities.Length; ++i)
332 entities[i] = _typeSystemServices.GetMemberEntity(members[i]);
334 return entities;
338 override public string ToString()
340 return FullName;
343 public IGenericTypeInfo GenericInfo
345 get
347 if (TypeDefinition.GenericParameters.Count != 0)
349 return this;
351 return null;
355 public IConstructedTypeInfo ConstructedInfo
357 get { return null; }
360 IGenericParameter[] IGenericTypeInfo.GenericParameters
364 if (_genericParameters == null)
366 _genericParameters = Array.ConvertAll<GenericParameterDeclaration, IGenericParameter>(
367 _typeDefinition.GenericParameters.ToArray(),
368 delegate(GenericParameterDeclaration gpd) { return (IGenericParameter)gpd.Entity; } );
371 return _genericParameters;
375 IType IGenericTypeInfo.ConstructType(IType[] arguments)
377 IType constructed = null;
378 if (!_constructedTypes.TryGetValue(arguments, out constructed))
380 constructed = CreateConstructedType(arguments);
381 _constructedTypes.Add(arguments, constructed);
384 return constructed;
387 protected virtual IType CreateConstructedType(IType[] arguments)
389 return new GenericConstructedType(_typeSystemServices, this, arguments);