2 // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
3 // All rights reserved.
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
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.
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.
29 namespace Boo
.Lang
.Compiler
.TypeSystem
32 using System
.Collections
;
33 using System
.Reflection
;
35 using Boo
.Lang
.Compiler
.Ast
;
36 using Attribute
= Boo
.Lang
.Compiler
.Ast
.Attribute
;
37 using Module
= Boo
.Lang
.Compiler
.Ast
.Module
;
39 public class TypeSystemServices
41 public DuckTypeImpl DuckType
;
43 public ExternalType IQuackFuType
;
45 public ExternalType ExceptionType
;
47 public ExternalType ApplicationExceptionType
;
49 public ExternalType MulticastDelegateType
;
51 public ExternalType DelegateType
;
53 public ExternalType IntPtrType
;
55 public ExternalType UIntPtrType
;
57 public ExternalType ObjectType
;
59 public ExternalType ValueTypeType
;
61 public ExternalType EnumType
;
63 public ExternalType RegexType
;
65 public ExternalType ArrayType
;
67 public ExternalType TypeType
;
69 public IArrayType ObjectArrayType
;
71 public ExternalType VoidType
;
73 public ExternalType StringType
;
75 public ExternalType BoolType
;
77 public ExternalType CharType
;
79 public ExternalType SByteType
;
81 public ExternalType ByteType
;
83 public ExternalType ShortType
;
85 public ExternalType UShortType
;
87 public ExternalType IntType
;
89 public ExternalType UIntType
;
91 public ExternalType LongType
;
93 public ExternalType ULongType
;
95 public ExternalType SingleType
;
97 public ExternalType DoubleType
;
99 public ExternalType DecimalType
;
101 public ExternalType TimeSpanType
;
103 protected ExternalType DateTimeType
;
105 public ExternalType RuntimeServicesType
;
107 public ExternalType BuiltinsType
;
109 public ExternalType ListType
;
111 public ExternalType HashType
;
113 public ExternalType ICallableType
;
115 public ExternalType IEnumerableType
;
117 public ExternalType IEnumeratorType
;
119 public ExternalType IEnumerableGenericType
;
121 public ExternalType IEnumeratorGenericType
;
123 public ExternalType ICollectionType
;
125 public ExternalType IListType
;
127 public ExternalType IDictionaryType
;
129 public ExternalType SystemAttribute
;
131 public ExternalType ConditionalAttribute
;
133 protected Hashtable _primitives
= new Hashtable();
135 protected Hashtable _entityCache
= new Hashtable();
137 protected Hashtable _arrayCache
= new Hashtable();
139 public static readonly IType ErrorEntity
= Error
.Default
;
141 public readonly BooCodeBuilder CodeBuilder
;
143 private StringBuilder _buffer
= new StringBuilder();
145 private Module _compilerGeneratedTypesModule
;
147 private Module _compilerGeneratedExtensionsModule
;
149 private ClassDefinition _compilerGeneratedExtensionsClass
;
151 protected readonly CompilerContext _context
;
153 private readonly AnonymousCallablesManager _anonymousCallablesManager
;
155 private readonly GenericsServices _genericsServices
;
157 public TypeSystemServices() : this(new CompilerContext())
161 public TypeSystemServices(CompilerContext context
)
163 if (null == context
) throw new ArgumentNullException("context");
166 _anonymousCallablesManager
= new AnonymousCallablesManager(this);
167 _genericsServices
= new GenericsServices(context
);
169 CodeBuilder
= new BooCodeBuilder(this);
171 Cache(typeof(Builtins
.duck
), DuckType
= new DuckTypeImpl(this));
172 Cache(IQuackFuType
= new ExternalType(this, typeof(IQuackFu
)));
173 Cache(VoidType
= new VoidTypeImpl(this));
174 Cache(ObjectType
= new ExternalType(this, Types
.Object
));
175 Cache(RegexType
= new ExternalType(this, Types
.Regex
));
176 Cache(ValueTypeType
= new ExternalType(this, typeof(ValueType
)));
177 Cache(EnumType
= new ExternalType(this, typeof(Enum
)));
178 Cache(ArrayType
= new ExternalType(this, Types
.Array
));
179 Cache(TypeType
= new ExternalType(this, Types
.Type
));
180 Cache(StringType
= new ExternalType(this, Types
.String
));
181 Cache(BoolType
= new ExternalType(this, Types
.Bool
));
182 Cache(SByteType
= new ExternalType(this, Types
.SByte
));
183 Cache(CharType
= new ExternalType(this, Types
.Char
));
184 Cache(ShortType
= new ExternalType(this, Types
.Short
));
185 Cache(IntType
= new ExternalType(this, Types
.Int
));
186 Cache(LongType
= new ExternalType(this, Types
.Long
));
187 Cache(ByteType
= new ExternalType(this, Types
.Byte
));
188 Cache(UShortType
= new ExternalType(this, Types
.UShort
));
189 Cache(UIntType
= new ExternalType(this, Types
.UInt
));
190 Cache(ULongType
= new ExternalType(this, Types
.ULong
));
191 Cache(SingleType
= new ExternalType(this, Types
.Single
));
192 Cache(DoubleType
= new ExternalType(this, Types
.Double
));
193 Cache(DecimalType
= new ExternalType(this, Types
.Decimal
));
194 Cache(TimeSpanType
= new ExternalType(this, Types
.TimeSpan
));
195 Cache(DateTimeType
= new ExternalType(this, Types
.DateTime
));
196 Cache(RuntimeServicesType
= new ExternalType(this, Types
.RuntimeServices
));
197 Cache(BuiltinsType
= new ExternalType(this, Types
.Builtins
));
198 Cache(ListType
= new ExternalType(this, Types
.List
));
199 Cache(HashType
= new ExternalType(this, Types
.Hash
));
200 Cache(ICallableType
= new ExternalType(this, Types
.ICallable
));
201 Cache(IEnumerableType
= new ExternalType(this, Types
.IEnumerable
));
202 Cache(IEnumeratorType
= new ExternalType(this, typeof(IEnumerator
)));
203 Cache(ICollectionType
= new ExternalType(this, Types
.ICollection
));
204 Cache(IListType
= new ExternalType(this, Types
.IList
));
205 Cache(IDictionaryType
= new ExternalType(this, Types
.IDictionary
));
206 Cache(ApplicationExceptionType
= new ExternalType(this, Types
.ApplicationException
));
207 Cache(ExceptionType
= new ExternalType(this, Types
.Exception
));
208 Cache(IntPtrType
= new ExternalType(this, Types
.IntPtr
));
209 Cache(UIntPtrType
= new ExternalType(this, Types
.UIntPtr
));
210 Cache(MulticastDelegateType
= new ExternalType(this, Types
.MulticastDelegate
));
211 Cache(DelegateType
= new ExternalType(this, Types
.Delegate
));
212 Cache(SystemAttribute
= new ExternalType(this, typeof(System
.Attribute
)));
213 Cache(ConditionalAttribute
= new ExternalType(this, typeof(System
.Diagnostics
.ConditionalAttribute
)));
214 Cache(IEnumerableGenericType
= new ExternalType(this, typeof(System
.Collections
.Generic
.IEnumerable
<>)));
215 Cache(IEnumeratorGenericType
= new ExternalType(this, typeof(System
.Collections
.Generic
.IEnumerator
<>)));
217 ObjectArrayType
= GetArrayType(ObjectType
, 1);
220 PrepareBuiltinFunctions();
224 public CompilerContext Context
226 get { return _context; }
229 public GenericsServices GenericsServices
231 get { return _genericsServices; }
234 public IType
GetMostGenericType(IType current
, IType candidate
)
236 if (current
.IsAssignableFrom(candidate
))
241 if (candidate
.IsAssignableFrom(current
))
246 if (IsNumberOrBool(current
) && IsNumberOrBool(candidate
))
248 return GetPromotedNumberType(current
, candidate
);
251 if (IsCallableType(current
) && IsCallableType(candidate
))
253 return ICallableType
;
256 if (current
.IsClass
&& candidate
.IsClass
)
258 if (current
== ObjectType
|| candidate
== ObjectType
)
262 if (current
.GetTypeDepth() < candidate
.GetTypeDepth())
264 return GetMostGenericType(current
.BaseType
, candidate
);
266 return GetMostGenericType(current
, candidate
.BaseType
);
271 public IType
GetPromotedNumberType(IType left
, IType right
)
273 if (left
== DecimalType
||
274 right
== DecimalType
)
278 if (left
== DoubleType
||
283 if (left
== SingleType
||
288 if (left
== ULongType
)
290 if (right
== SByteType
||
291 right
== ShortType
||
295 // This is against the C# spec but allows expressions like:
299 // C# disallows mixing ulongs and signed numbers
300 // but in the above case it promotes the constant to ulong
301 // and the result is ulong.
302 // Since its too late here to promote the constant,
303 // maybe we should return LongType. I didn't chose ULongType
304 // because in other cases <unsigned> <op> <signed> returns <signed>.
309 if (right
== ULongType
)
311 if (left
== SByteType
||
316 // This is against the C# spec but allows expressions like:
320 // C# disallows mixing ulongs and signed numbers
321 // but in the above case it promotes the constant to ulong
322 // and the result is ulong.
323 // Since its too late here to promote the constant,
324 // maybe we should return LongType. I didn't chose ULongType
325 // because in other cases <signed> <op> <unsigned> returns <signed>.
330 if (left
== LongType
||
335 if (left
== UIntType
)
337 if (right
== SByteType
||
338 right
== ShortType
||
341 // This is allowed per C# spec and y is long:
344 // C# promotes <uint> <op> <signed> to <long> also
345 // but in the above case it promotes the constant to uint first
346 // and the result of "x + 1" is uint.
347 // Since its too late here to promote the constant,
348 // "y = x + 1" will be long in boo.
353 if (right
== UIntType
)
355 if (left
== SByteType
||
359 // This is allowed per C# spec and y is long:
362 // C# promotes <signed> <op> <uint> to <long> also
363 // but in the above case it promotes the constant to uint first
364 // and the result of "1 + x" is uint.
365 // Since its too late here to promote the constant,
366 // "y = x + 1" will be long in boo.
371 if (left
== IntType
||
374 right
== ShortType
||
375 left
== UShortType
||
376 right
== UShortType
||
387 public static bool IsReadOnlyField(IField field
)
389 return field
.IsInitOnly
|| field
.IsLiteral
;
392 public bool IsCallable(IType type
)
394 return (TypeType
== type
) || IsCallableType(type
) || IsDuckType(type
);
397 public virtual bool IsDuckTyped(Expression expression
)
399 IType type
= expression
.ExpressionType
;
400 return null != type
&& this.IsDuckType(type
);
403 public bool IsQuackBuiltin(Expression node
)
405 return IsQuackBuiltin(GetOptionalEntity(node
));
408 public bool IsQuackBuiltin(IEntity entity
)
410 return BuiltinFunction
.Quack
== entity
;
413 public bool IsDuckType(IType type
)
417 throw new ArgumentNullException("type");
421 || KnowsQuackFu(type
)
422 || (_context
.Parameters
.Ducky
423 && (type
== ObjectType
)));
426 public bool KnowsQuackFu(IType type
)
428 return type
.IsSubclassOf(IQuackFuType
);
431 bool IsCallableType(IType type
)
433 return (ICallableType
.IsAssignableFrom(type
)) || (type
is ICallableType
);
436 public AnonymousCallableType
GetCallableType(IMethod method
)
438 CallableSignature signature
= new CallableSignature(method
);
439 return GetCallableType(signature
);
442 public AnonymousCallableType
GetCallableType(CallableSignature signature
)
444 return _anonymousCallablesManager
.GetCallableType(signature
);
447 public virtual IType
GetConcreteCallableType(Node sourceNode
, CallableSignature signature
)
449 return _anonymousCallablesManager
.GetConcreteCallableType(sourceNode
, signature
);
452 public virtual IType
GetConcreteCallableType(Node sourceNode
, AnonymousCallableType anonymousType
)
454 return _anonymousCallablesManager
.GetConcreteCallableType(sourceNode
, anonymousType
);
457 public IType
GetEnumeratorItemType(IType iteratorType
)
459 // Arrays are enumerators of their element type
460 if (iteratorType
.IsArray
) return iteratorType
.GetElementType();
462 // String are enumerators of char
463 if (StringType
== iteratorType
) return CharType
;
465 // Try to use an EnumerableItemType attribute
466 if (iteratorType
.IsClass
)
468 IType enumeratorItemType
= GetEnumeratorItemTypeFromAttribute(iteratorType
);
469 if (null != enumeratorItemType
) return enumeratorItemType
;
472 // Try to use a generic IEnumerable interface
473 IType genericItemType
= GetGenericEnumerableItemType(iteratorType
);
474 if (null != genericItemType
) return genericItemType
;
476 // If none of these work, the type is an enumerator of object
480 public IType
GetExpressionType(Expression node
)
482 IType type
= node
.ExpressionType
;
485 throw CompilerErrorFactory
.InvalidNode(node
);
490 public IType
GetConcreteExpressionType(Expression expression
)
492 IType type
= GetExpressionType(expression
);
493 AnonymousCallableType anonymousType
= type
as AnonymousCallableType
;
494 if (null != anonymousType
)
496 IType concreteType
= GetConcreteCallableType(expression
, anonymousType
);
497 expression
.ExpressionType
= concreteType
;
503 public void MapToConcreteExpressionTypes(ExpressionCollection items
)
505 foreach (Expression item
in items
)
507 GetConcreteExpressionType(item
);
511 public ClassDefinition
GetCompilerGeneratedExtensionsClass()
513 if (null == _compilerGeneratedExtensionsClass
)
515 BooClassBuilder builder
= CodeBuilder
.CreateClass("CompilerGeneratedExtensions");
516 builder
.Modifiers
= TypeMemberModifiers
.Final
|TypeMemberModifiers
.Transient
|TypeMemberModifiers
.Public
;
517 builder
.AddBaseType(ObjectType
);
519 BooMethodBuilder ctor
= builder
.AddConstructor();
520 ctor
.Modifiers
= TypeMemberModifiers
.Private
;
522 CodeBuilder
.CreateSuperConstructorInvocation(ObjectType
));
524 ClassDefinition cd
= builder
.ClassDefinition
;
525 Module module
= GetCompilerGeneratedExtensionsModule();
526 module
.Members
.Add(cd
);
527 ((ModuleEntity
)module
.Entity
).InitializeModuleClass(cd
);
529 _compilerGeneratedExtensionsClass
= cd
;
531 return _compilerGeneratedExtensionsClass
;
534 public Module
GetCompilerGeneratedExtensionsModule()
536 if (null == _compilerGeneratedExtensionsModule
)
538 _compilerGeneratedExtensionsModule
= NewModule(null, "CompilerGeneratedExtensions");
540 return _compilerGeneratedExtensionsModule
;
543 public void AddCompilerGeneratedType(TypeDefinition type
)
545 GetCompilerGeneratedTypesModule().Members
.Add(type
);
548 public Module
GetCompilerGeneratedTypesModule()
550 if (null == _compilerGeneratedTypesModule
)
552 _compilerGeneratedTypesModule
= NewModule("CompilerGenerated");
554 return _compilerGeneratedTypesModule
;
557 private Module
NewModule(string nameSpace
)
559 return NewModule(nameSpace
, nameSpace
);
562 private Module
NewModule(string nameSpace
, string moduleName
)
564 Module module
= new Module();
565 module
.Name
= moduleName
;
566 if (null != nameSpace
) module
.Namespace
= new NamespaceDeclaration(nameSpace
);
567 module
.Entity
= new ModuleEntity(_context
.NameResolutionService
, this, module
);
568 _context
.CompileUnit
.Modules
.Add(module
);
572 public ClassDefinition
CreateCallableDefinition(string name
)
574 ClassDefinition cd
= new ClassDefinition();
575 cd
.IsSynthetic
= true;
576 cd
.BaseTypes
.Add(CodeBuilder
.CreateTypeReference(this.MulticastDelegateType
));
577 cd
.BaseTypes
.Add(CodeBuilder
.CreateTypeReference(this.ICallableType
));
579 cd
.Modifiers
= TypeMemberModifiers
.Final
;
580 cd
.Members
.Add(CreateCallableConstructor());
581 cd
.Members
.Add(CreateCallMethod());
582 cd
.Entity
= new InternalCallableType(this, cd
);
586 Method
CreateCallMethod()
588 Method method
= new Method("Call");
589 method
.IsSynthetic
= true;
590 method
.Modifiers
= TypeMemberModifiers
.Public
|TypeMemberModifiers
.Virtual
;
591 method
.Parameters
.Add(CodeBuilder
.CreateParameterDeclaration(1, "args", ObjectArrayType
));
592 method
.ReturnType
= CodeBuilder
.CreateTypeReference(ObjectType
);
593 method
.Entity
= new InternalMethod(this, method
);
597 Constructor
CreateCallableConstructor()
599 Constructor constructor
= new Constructor();
600 constructor
.IsSynthetic
= true;
601 constructor
.Modifiers
= TypeMemberModifiers
.Public
;
602 constructor
.ImplementationFlags
= MethodImplementationFlags
.Runtime
;
603 constructor
.Parameters
.Add(
604 CodeBuilder
.CreateParameterDeclaration(1, "instance", ObjectType
));
605 constructor
.Parameters
.Add(
606 CodeBuilder
.CreateParameterDeclaration(2, "method", IntPtrType
));
607 constructor
.Entity
= new InternalConstructor(this, constructor
);
611 public bool AreTypesRelated(IType lhs
, IType rhs
)
613 ICallableType ctype
= lhs
as ICallableType
;
616 return ctype
.IsAssignableFrom(rhs
)
617 || ctype
.IsSubclassOf(rhs
);
620 return lhs
.IsAssignableFrom(rhs
)
621 || (lhs
.IsInterface
&& !rhs
.IsFinal
)
622 || (rhs
.IsInterface
&& !lhs
.IsFinal
)
623 || CanBeReachedByDownCastOrPromotion(lhs
, rhs
)
624 || FindImplicitConversionOperator(rhs
,lhs
) != null;
627 public IMethod
FindExplicitConversionOperator(IType fromType
, IType toType
)
629 return FindConversionOperator("op_Explicit", fromType
, toType
);
632 public IMethod
FindImplicitConversionOperator(IType fromType
, IType toType
)
634 return FindConversionOperator("op_Implicit", fromType
, toType
);
637 public IMethod
FindConversionOperator(string name
, IType fromType
, IType toType
)
639 while (fromType
!= this.ObjectType
)
641 IMethod method
= FindConversionOperator(name
, fromType
, toType
, fromType
.GetMembers());
642 if (null != method
) return method
;
643 method
= FindConversionOperator(name
, fromType
, toType
, toType
.GetMembers());
644 if (null != method
) return method
;
645 method
= FindConversionOperator(name
, fromType
, toType
, FindExtension(fromType
, name
));
646 if (null != method
) return method
;
648 fromType
= fromType
.BaseType
;
649 if (null == fromType
) break;
654 private IEntity
[] FindExtension(IType fromType
, string name
)
656 IEntity extension
= _context
.NameResolutionService
.ResolveExtension(fromType
, name
);
657 if (null == extension
) return Ambiguous
.NoEntities
;
659 Ambiguous a
= extension
as Ambiguous
;
660 if (null != a
) return a
.Entities
;
661 return new IEntity
[] { extension }
;
664 IMethod
FindConversionOperator(string name
, IType fromType
, IType toType
, IEntity
[] candidates
)
666 foreach (IEntity entity
in candidates
)
668 if (EntityType
.Method
!= entity
.EntityType
|| name
!= entity
.Name
) continue;
669 IMethod method
= (IMethod
)entity
;
670 if (IsConversionOperator(method
, fromType
, toType
)) return method
;
675 bool IsConversionOperator(IMethod method
, IType fromType
, IType toType
)
677 if (!method
.IsStatic
) return false;
678 if (method
.ReturnType
!= toType
) return false;
679 IParameter
[] parameters
= method
.GetParameters();
680 return (1 == parameters
.Length
&& fromType
== parameters
[0].Type
);
683 public bool IsCallableTypeAssignableFrom(ICallableType lhs
, IType rhs
)
685 if (lhs
== rhs
) return true;
686 if (Null
.Default
== rhs
) return true;
688 ICallableType other
= rhs
as ICallableType
;
689 if (null == other
) return false;
691 CallableSignature lvalue
= lhs
.GetSignature();
692 CallableSignature rvalue
= other
.GetSignature();
693 if (lvalue
== rvalue
) return true;
695 IParameter
[] lparams
= lvalue
.Parameters
;
696 IParameter
[] rparams
= rvalue
.Parameters
;
697 if (lparams
.Length
< rparams
.Length
) return false;
699 for (int i
=0; i
<rparams
.Length
; ++i
)
701 if (!AreTypesRelated(lparams
[i
].Type
, rparams
[i
].Type
)) return false;
704 return CompatibleReturnTypes(lvalue
, rvalue
);
707 private bool CompatibleReturnTypes(CallableSignature lvalue
, CallableSignature rvalue
)
709 if (VoidType
!= lvalue
.ReturnType
&& VoidType
!= rvalue
.ReturnType
)
711 return AreTypesRelated(lvalue
.ReturnType
, rvalue
.ReturnType
);
717 public static bool CheckOverrideSignature(IMethod impl
, IMethod baseMethod
)
719 return CheckOverrideSignature(impl
.GetParameters(), baseMethod
.GetParameters());
722 public static bool CheckOverrideSignature(IParameter
[] implParameters
, IParameter
[] baseParameters
)
724 if (implParameters
.Length
!= baseParameters
.Length
) return false;
726 for (int i
=0; i
<implParameters
.Length
; ++i
)
728 IParameter implParameter
= implParameters
[i
];
729 IParameter baseParameter
= baseParameters
[i
];
730 IType implType
= implParameter
.Type
;
731 IType baseType
= baseParameter
.Type
;
733 if (baseType
.IsByRef
)
735 if (!implParameter
.IsByRef
) return false;
736 if (baseType
.GetElementType() != implType
) return false;
740 if (implType
!= baseType
) return false;
746 public virtual bool CanBeReachedByDownCastOrPromotion(IType expectedType
, IType actualType
)
748 return CanBeReachedByDowncast(expectedType
, actualType
)
749 || CanBeReachedByPromotion(expectedType
, actualType
);
752 public virtual bool CanBeReachedByDowncast(IType expectedType
, IType actualType
)
754 return actualType
.IsAssignableFrom(expectedType
);
757 public virtual bool CanBeReachedByPromotion(IType expectedType
, IType actualType
)
759 return (expectedType
.IsValueType
760 && IsNumber(expectedType
)
761 && IsNumber(actualType
));
764 public bool CanBeExplicitlyCastToInteger(IType type
)
766 return type
.IsEnum
|| type
== this.CharType
;
769 public static bool ContainsMethodsOnly(List members
)
771 foreach (IEntity member
in members
)
773 if (EntityType
.Method
!= member
.EntityType
) return false;
778 public bool IsIntegerNumber(IType type
)
781 type
== this.ShortType
||
782 type
== this.IntType
||
783 type
== this.LongType
||
784 type
== this.SByteType
||
785 type
== this.UShortType
||
786 type
== this.UIntType
||
787 type
== this.ULongType
||
788 type
== this.ByteType
;
791 public bool IsIntegerOrBool(IType type
)
793 return BoolType
== type
|| IsIntegerNumber(type
);
796 public bool IsNumberOrBool(IType type
)
798 return BoolType
== type
|| IsNumber(type
);
801 public bool IsNumber(IType type
)
804 IsPrimitiveNumber(type
) ||
805 type
== this.DecimalType
;
808 public bool IsPrimitiveNumber(IType type
)
811 IsIntegerNumber(type
) ||
812 type
== this.DoubleType
||
813 type
== this.SingleType
;
816 public static bool IsUnknown(Expression node
)
818 IType type
= node
.ExpressionType
;
821 return IsUnknown(type
);
826 public static bool IsUnknown(IType tag
)
828 return EntityType
.Unknown
== tag
.EntityType
;
831 public static bool IsError(Expression node
)
833 IType type
= node
.ExpressionType
;
836 return IsError(type
);
841 public static bool IsErrorAny(ExpressionCollection collection
)
843 foreach (Expression n
in collection
)
853 public bool IsBuiltin(IEntity tag
)
855 if (EntityType
.Method
== tag
.EntityType
)
857 return BuiltinsType
== ((IMethod
)tag
).DeclaringType
;
862 public static bool IsError(IEntity tag
)
864 return EntityType
.Error
== tag
.EntityType
;
867 public static TypeMemberModifiers
GetAccess(IAccessibleMember member
)
871 return TypeMemberModifiers
.Public
;
873 else if (member
.IsProtected
)
875 return TypeMemberModifiers
.Protected
;
877 return TypeMemberModifiers
.Private
;
880 public static IEntity
[] GetAllMembers(INamespace entity
)
882 List members
= new List();
883 GetAllMembers(members
, entity
);
884 return (IEntity
[])members
.ToArray(new IEntity
[members
.Count
]);
887 private static void GetAllMembers(List members
, INamespace entity
)
889 if (null == entity
) return;
891 IType type
= entity
as IType
;
894 members
.ExtendUnique(type
.GetMembers());
895 GetAllMembers(members
, type
.BaseType
);
899 members
.Extend(entity
.GetMembers());
903 static object EntityAnnotationKey
= new object();
905 public static void Bind(Node node
, IEntity entity
)
907 if (null == node
) throw new ArgumentNullException("node");
908 node
[EntityAnnotationKey
] = entity
;
911 public static IEntity
GetOptionalEntity(Node node
)
913 if (null == node
) throw new ArgumentNullException("node");
914 return (IEntity
)node
[EntityAnnotationKey
];
917 public static IEntity
GetEntity(Node node
)
919 IEntity tag
= GetOptionalEntity(node
);
920 if (null == tag
) InvalidNode(node
);
925 public static IType
GetReferencedType(Expression typeref
)
927 switch (typeref
.NodeType
)
929 case NodeType
.TypeofExpression
:
931 return GetType(((TypeofExpression
)typeref
).Type
);
933 case NodeType
.ReferenceExpression
:
934 case NodeType
.MemberReferenceExpression
:
935 case NodeType
.GenericReferenceExpression
:
937 return typeref
.Entity
as IType
;
943 public virtual bool IsModule(Type type
)
947 && !type
.IsNestedPublic
948 && MetadataUtil
.IsAttributeDefined(type
, Types
.ModuleAttribute
);
951 public bool IsAttribute(IType type
)
953 return type
.IsSubclassOf(SystemAttribute
);
956 public static IType
GetType(Node node
)
958 return ((ITypedEntity
)GetEntity(node
)).Type
;
961 public IType
Map(Type type
)
963 ExternalType entity
= (ExternalType
)_entityCache
[type
];
966 if (type
.IsArray
) return GetArrayType(Map(type
.GetElementType()), type
.GetArrayRank());
967 entity
= CreateEntityForType(type
);
973 private ExternalType
CreateEntityForType(Type type
)
975 if (type
.IsGenericParameter
) return new ExternalGenericParameter(this, type
);
976 if (type
.IsSubclassOf(Types
.MulticastDelegate
)) return new ExternalCallableType(this, type
);
977 return new ExternalType(this, type
);
980 public IArrayType
GetArrayType(IType elementType
, int rank
)
982 ArrayHash key
= new ArrayHash(elementType
, rank
);
983 IArrayType entity
= (IArrayType
)_arrayCache
[key
];
986 entity
= new ArrayType(this, elementType
, rank
);
987 _arrayCache
.Add(key
, entity
);
992 protected class ArrayHash
997 public ArrayHash(IType elementType
, int rank
)
1003 public override int GetHashCode()
1005 return _type
.GetHashCode() ^ _rank
;
1008 public override bool Equals(object obj
)
1010 return ((ArrayHash
)obj
)._type
== _type
&& ((ArrayHash
)obj
)._rank
== _rank
;
1014 public IParameter
[] Map(ParameterDeclarationCollection parameters
)
1016 IParameter
[] mapped
= new IParameter
[parameters
.Count
];
1017 for (int i
=0; i
<mapped
.Length
; ++i
)
1019 mapped
[i
] = (IParameter
)GetEntity(parameters
[i
]);
1024 public IParameter
[] Map(ParameterInfo
[] parameters
)
1026 IParameter
[] mapped
= new IParameter
[parameters
.Length
];
1027 for (int i
=0; i
<parameters
.Length
; ++i
)
1029 mapped
[i
] = new ExternalParameter(this, parameters
[i
]);
1034 public IConstructor
Map(ConstructorInfo constructor
)
1036 object key
= GetCacheKey(constructor
);
1037 IConstructor entity
= (IConstructor
)_entityCache
[key
];
1040 entity
= new ExternalConstructor(this, constructor
);
1041 _entityCache
[key
] = entity
;
1046 public IMethod
Map(MethodInfo method
)
1048 object key
= GetCacheKey(method
);
1049 IMethod entity
= (IMethod
)_entityCache
[key
];
1052 entity
= new ExternalMethod(this, method
);
1053 _entityCache
[key
] = entity
;
1058 public IEntity
Map(MemberInfo
[] info
)
1060 if (info
.Length
> 1)
1062 IEntity
[] tags
= new IEntity
[info
.Length
];
1063 for (int i
=0; i
<tags
.Length
; ++i
)
1065 tags
[i
] = Map(info
[i
]);
1067 return new Ambiguous(tags
);
1069 if (info
.Length
> 0)
1071 return Map(info
[0]);
1076 public IEntity
Map(MemberInfo mi
)
1078 IEntity tag
= (IEntity
)_entityCache
[GetCacheKey(mi
)];
1081 switch (mi
.MemberType
)
1083 case MemberTypes
.Method
:
1085 return Map((MethodInfo
)mi
);
1088 case MemberTypes
.Constructor
:
1090 return Map((ConstructorInfo
)mi
);
1093 case MemberTypes
.Field
:
1095 tag
= new ExternalField(this, (FieldInfo
)mi
);
1099 case MemberTypes
.Property
:
1101 tag
= new ExternalProperty(this, (PropertyInfo
)mi
);
1105 case MemberTypes
.Event
:
1107 tag
= new ExternalEvent(this, (EventInfo
)mi
);
1111 case MemberTypes
.NestedType
:
1113 return Map((Type
)mi
);
1118 throw new NotImplementedException(mi
.ToString());
1121 _entityCache
.Add(GetCacheKey(mi
), tag
);
1126 public string GetSignature(IEntityWithParameters method
)
1128 return GetSignature(method
, true);
1131 public string GetSignature(IEntityWithParameters method
, bool includeFullName
)
1134 if (includeFullName
)
1136 _buffer
.Append(method
.FullName
);
1140 _buffer
.Append(method
.Name
);
1142 _buffer
.Append("(");
1144 IParameter
[] parameters
= method
.GetParameters();
1145 for (int i
=0; i
<parameters
.Length
; ++i
)
1147 if (i
> 0) { _buffer.Append(", "); }
1148 if (method
.AcceptVarArgs
&& i
== parameters
.Length
-1) { _buffer.Append('*'); }
1149 _buffer
.Append(parameters
[i
].Type
);
1151 _buffer
.Append(")");
1152 return _buffer
.ToString();
1155 public object GetCacheKey(MemberInfo mi
)
1160 public IEntity
ResolvePrimitive(string name
)
1162 return (IEntity
)_primitives
[name
];
1165 public bool IsPrimitive(string name
)
1167 return _primitives
.ContainsKey(name
);
1171 /// checks if the passed type will be equivalente to
1172 /// System.Object in runtime (accounting for the presence
1173 /// of duck typing).
1175 public bool IsSystemObject(IType type
)
1177 return type
== ObjectType
|| type
== DuckType
;
1180 public bool RequiresBoxing(IType expectedType
, IType actualType
)
1182 if (!actualType
.IsValueType
) return false;
1183 return IsSystemObject(expectedType
);
1186 protected virtual void PreparePrimitives()
1188 AddPrimitiveType("duck", DuckType
);
1189 AddPrimitiveType("void", VoidType
);
1190 AddPrimitiveType("object", ObjectType
);
1191 AddPrimitiveType("bool", BoolType
);
1192 AddPrimitiveType("sbyte", SByteType
);
1193 AddPrimitiveType("byte", ByteType
);
1194 AddPrimitiveType("short", ShortType
);
1195 AddPrimitiveType("ushort", UShortType
);
1196 AddPrimitiveType("int", IntType
);
1197 AddPrimitiveType("uint", UIntType
);
1198 AddPrimitiveType("long", LongType
);
1199 AddPrimitiveType("ulong", ULongType
);
1200 AddPrimitiveType("single", SingleType
);
1201 AddPrimitiveType("double", DoubleType
);
1202 AddPrimitiveType("decimal", DecimalType
);
1203 AddPrimitiveType("char", CharType
);
1204 AddPrimitiveType("string", StringType
);
1205 AddPrimitiveType("regex", RegexType
);
1206 AddPrimitiveType("date", DateTimeType
);
1207 AddPrimitiveType("timespan", TimeSpanType
);
1208 AddPrimitiveType("callable", ICallableType
);
1211 protected virtual void PrepareBuiltinFunctions()
1213 AddBuiltin(BuiltinFunction
.Len
);
1214 AddBuiltin(BuiltinFunction
.AddressOf
);
1215 AddBuiltin(BuiltinFunction
.Eval
);
1216 AddBuiltin(BuiltinFunction
.Switch
);
1219 protected void AddPrimitiveType(string name
, ExternalType type
)
1221 _primitives
[name
] = type
;
1222 type
.PrimitiveName
= name
;
1225 protected void AddBuiltin(BuiltinFunction function
)
1227 _primitives
[function
.Name
] = function
;
1230 void Cache(ExternalType tag
)
1232 _entityCache
[tag
.ActualType
] = tag
;
1235 void Cache(object key
, IType tag
)
1237 _entityCache
[key
] = tag
;
1240 public IConstructor
GetDefaultConstructor(IType type
)
1242 IConstructor
[] constructors
= type
.GetConstructors();
1243 for (int i
=0; i
<constructors
.Length
; ++i
)
1245 IConstructor constructor
= constructors
[i
];
1246 if (0 == constructor
.GetParameters().Length
)
1254 IType
GetExternalEnumeratorItemType(IType iteratorType
)
1256 Type type
= ((ExternalType
)iteratorType
).ActualType
;
1257 EnumeratorItemTypeAttribute attribute
= (EnumeratorItemTypeAttribute
)System
.Attribute
.GetCustomAttribute(type
, typeof(EnumeratorItemTypeAttribute
));
1258 if (null != attribute
)
1260 return Map(attribute
.ItemType
);
1265 IType
GetEnumeratorItemTypeFromAttribute(IType iteratorType
)
1267 // If iterator type is external get its attributes via reflection
1268 if (iteratorType
is ExternalType
)
1270 return GetExternalEnumeratorItemType(iteratorType
);
1273 // If iterator type is a generic constructed type, map its attribute from its definition
1274 GenericConstructedType constructedType
= iteratorType
as GenericConstructedType
;
1275 if (constructedType
!= null)
1277 return constructedType
.GenericMapping
.Map(
1278 GetEnumeratorItemTypeFromAttribute(constructedType
.GenericDefinition
));
1281 // If iterator type is internal get its attributes from its type definition
1282 AbstractInternalType internalType
= (AbstractInternalType
)iteratorType
;
1283 IType enumeratorItemTypeAttribute
= Map(typeof(EnumeratorItemTypeAttribute
));
1284 foreach (Attribute attribute
in internalType
.TypeDefinition
.Attributes
)
1286 IConstructor constructor
= GetEntity(attribute
) as IConstructor
;
1287 if (null != constructor
)
1289 if (constructor
.DeclaringType
== enumeratorItemTypeAttribute
)
1291 return GetType(attribute
.Arguments
[0]);
1298 public IType
GetGenericEnumerableItemType(IType iteratorType
)
1300 // Arrays implicitly implement IEnumerable[of element type]
1301 if (iteratorType
is ArrayType
) return iteratorType
.GetElementType();
1303 // If type is not an array, try to find IEnumerable[of some type] in its interfaces
1304 IType itemType
= null;
1305 foreach (IType type
in GenericsServices
.FindConstructedTypes(iteratorType
, IEnumerableGenericType
))
1307 IType candidateItemType
= type
.ConstructedInfo
.GenericArguments
[0];
1309 if (itemType
!= null)
1311 itemType
= GetMostGenericType(itemType
, candidateItemType
);
1315 itemType
= candidateItemType
;
1322 public IEntity
GetMemberEntity(TypeMember member
)
1324 if (null == member
.Entity
)
1326 member
.Entity
= CreateEntity(member
);
1328 return member
.Entity
;
1331 private IEntity
CreateEntity(TypeMember member
)
1333 switch (member
.NodeType
)
1335 case NodeType
.ClassDefinition
:
1336 return new InternalClass(this, (TypeDefinition
) member
);
1337 case NodeType
.Field
:
1338 return new InternalField((Field
)member
);
1339 case NodeType
.EnumMember
:
1340 return new InternalEnumMember(this, (EnumMember
)member
);
1341 case NodeType
.Method
:
1342 return new InternalMethod(this, (Method
)member
);
1343 case NodeType
.Constructor
:
1344 return new InternalConstructor(this, (Constructor
)member
);
1345 case NodeType
.Property
:
1346 return new InternalProperty(this, (Property
)member
);
1347 case NodeType
.Event
:
1348 return new InternalEvent(this, (Event
)member
);
1350 throw new ArgumentException("Member type not supported: " + member
);
1354 private static void InvalidNode(Node node
)
1356 throw CompilerErrorFactory
.InvalidNode(node
);
1359 public class DuckTypeImpl
: ExternalType
1361 public DuckTypeImpl(TypeSystemServices typeSystemServices
) :
1362 base(typeSystemServices
, Types
.Object
)
1367 #region VoidTypeImpl
1368 class VoidTypeImpl
: ExternalType
1370 internal VoidTypeImpl(TypeSystemServices typeSystemServices
) : base(typeSystemServices
, Types
.Void
)
1374 override public bool Resolve(List targetList
, string name
, EntityType flags
)
1379 override public bool IsSubclassOf(IType other
)
1384 override public bool IsAssignableFrom(IType other
)