PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Boo.Lang.Compiler/TypeSystem/TypeSystemServices.cs

https://github.com/boo/boo-lang
C# | 1409 lines | 1120 code | 213 blank | 76 comment | 255 complexity | 1294cea777648845d01ea335c3c56b17 MD5 | raw file
Possible License(s): GPL-2.0
  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
  28. namespace Boo.Lang.Compiler.TypeSystem
  29. {
  30. using System;
  31. using System.Collections;
  32. using System.Reflection;
  33. using System.Text;
  34. using Boo.Lang.Compiler.Ast;
  35. using Attribute = Boo.Lang.Compiler.Ast.Attribute;
  36. using Module = Boo.Lang.Compiler.Ast.Module;
  37. public class TypeSystemServices
  38. {
  39. public DuckTypeImpl DuckType;
  40. public ExternalType IQuackFuType;
  41. public ExternalType MulticastDelegateType;
  42. public ExternalType DelegateType;
  43. public ExternalType IntPtrType;
  44. public ExternalType UIntPtrType;
  45. public ExternalType ObjectType;
  46. public ExternalType ValueTypeType;
  47. public ExternalType EnumType;
  48. public ExternalType RegexType;
  49. public ExternalType ArrayType;
  50. public ExternalType TypeType;
  51. public IArrayType ObjectArrayType;
  52. public ExternalType VoidType;
  53. public ExternalType StringType;
  54. public ExternalType BoolType;
  55. public ExternalType CharType;
  56. public ExternalType SByteType;
  57. public ExternalType ByteType;
  58. public ExternalType ShortType;
  59. public ExternalType UShortType;
  60. public ExternalType IntType;
  61. public ExternalType UIntType;
  62. public ExternalType LongType;
  63. public ExternalType ULongType;
  64. public ExternalType SingleType;
  65. public ExternalType DoubleType;
  66. public ExternalType DecimalType;
  67. public ExternalType TimeSpanType;
  68. protected ExternalType DateTimeType;
  69. public ExternalType RuntimeServicesType;
  70. public ExternalType BuiltinsType;
  71. public ExternalType ListType;
  72. public ExternalType HashType;
  73. public ExternalType ICallableType;
  74. public ExternalType IEnumerableType;
  75. public ExternalType IEnumeratorType;
  76. public ExternalType IEnumerableGenericType;
  77. public ExternalType IEnumeratorGenericType;
  78. public ExternalType ICollectionType;
  79. public ExternalType IListType;
  80. public ExternalType IDictionaryType;
  81. public ExternalType SystemAttribute;
  82. public ExternalType ConditionalAttribute;
  83. protected Hashtable _primitives = new Hashtable();
  84. protected Hashtable _entityCache = new Hashtable();
  85. protected Hashtable _arrayCache = new Hashtable();
  86. public static readonly IType ErrorEntity = Error.Default;
  87. public readonly BooCodeBuilder CodeBuilder;
  88. private StringBuilder _buffer = new StringBuilder();
  89. private Module _compilerGeneratedTypesModule;
  90. private Module _compilerGeneratedExtensionsModule;
  91. private ClassDefinition _compilerGeneratedExtensionsClass;
  92. protected readonly CompilerContext _context;
  93. private readonly AnonymousCallablesManager _anonymousCallablesManager;
  94. private readonly GenericsServices _genericsServices;
  95. public TypeSystemServices() : this(new CompilerContext())
  96. {
  97. }
  98. public TypeSystemServices(CompilerContext context)
  99. {
  100. if (null == context) throw new ArgumentNullException("context");
  101. _context = context;
  102. _anonymousCallablesManager = new AnonymousCallablesManager(this);
  103. _genericsServices = new GenericsServices(context);
  104. CodeBuilder = new BooCodeBuilder(this);
  105. Cache(typeof(Builtins.duck), DuckType = new DuckTypeImpl(this));
  106. Cache(IQuackFuType = new ExternalType(this, typeof(IQuackFu)));
  107. Cache(VoidType = new VoidTypeImpl(this));
  108. Cache(ObjectType = new ExternalType(this, Types.Object));
  109. Cache(RegexType = new ExternalType(this, Types.Regex));
  110. Cache(ValueTypeType = new ExternalType(this, typeof(ValueType)));
  111. Cache(EnumType = new ExternalType(this, typeof(Enum)));
  112. Cache(ArrayType = new ExternalType(this, Types.Array));
  113. Cache(TypeType = new ExternalType(this, Types.Type));
  114. Cache(StringType = new ExternalType(this, Types.String));
  115. Cache(BoolType = new ExternalType(this, Types.Bool));
  116. Cache(SByteType = new ExternalType(this, Types.SByte));
  117. Cache(CharType = new ExternalType(this, Types.Char));
  118. Cache(ShortType = new ExternalType(this, Types.Short));
  119. Cache(IntType = new ExternalType(this, Types.Int));
  120. Cache(LongType = new ExternalType(this, Types.Long));
  121. Cache(ByteType = new ExternalType(this, Types.Byte));
  122. Cache(UShortType = new ExternalType(this, Types.UShort));
  123. Cache(UIntType = new ExternalType(this, Types.UInt));
  124. Cache(ULongType = new ExternalType(this, Types.ULong));
  125. Cache(SingleType = new ExternalType(this, Types.Single));
  126. Cache(DoubleType = new ExternalType(this, Types.Double));
  127. Cache(DecimalType = new ExternalType(this, Types.Decimal));
  128. Cache(TimeSpanType = new ExternalType(this, Types.TimeSpan));
  129. Cache(DateTimeType = new ExternalType(this, Types.DateTime));
  130. Cache(RuntimeServicesType = new ExternalType(this, Types.RuntimeServices));
  131. Cache(BuiltinsType = new ExternalType(this, Types.Builtins));
  132. Cache(ListType = new ExternalType(this, Types.List));
  133. Cache(HashType = new ExternalType(this, Types.Hash));
  134. Cache(ICallableType = new ExternalType(this, Types.ICallable));
  135. Cache(IEnumerableType = new ExternalType(this, Types.IEnumerable));
  136. Cache(IEnumeratorType = new ExternalType(this, typeof(IEnumerator)));
  137. Cache(ICollectionType = new ExternalType(this, Types.ICollection));
  138. Cache(IListType = new ExternalType(this, Types.IList));
  139. Cache(IDictionaryType = new ExternalType(this, Types.IDictionary));
  140. Cache(IntPtrType = new ExternalType(this, Types.IntPtr));
  141. Cache(UIntPtrType = new ExternalType(this, Types.UIntPtr));
  142. Cache(MulticastDelegateType = new ExternalType(this, Types.MulticastDelegate));
  143. Cache(DelegateType = new ExternalType(this, Types.Delegate));
  144. Cache(SystemAttribute = new ExternalType(this, typeof(System.Attribute)));
  145. Cache(ConditionalAttribute = new ExternalType(this, typeof(System.Diagnostics.ConditionalAttribute)));
  146. Cache(IEnumerableGenericType = new ExternalType(this, typeof(System.Collections.Generic.IEnumerable<>)));
  147. Cache(IEnumeratorGenericType = new ExternalType(this, typeof(System.Collections.Generic.IEnumerator<>)));
  148. ObjectArrayType = GetArrayType(ObjectType, 1);
  149. PreparePrimitives();
  150. PrepareBuiltinFunctions();
  151. }
  152. public CompilerContext Context
  153. {
  154. get { return _context; }
  155. }
  156. public GenericsServices GenericsServices
  157. {
  158. get { return _genericsServices; }
  159. }
  160. public IType GetMostGenericType(IType current, IType candidate)
  161. {
  162. if (current.IsAssignableFrom(candidate))
  163. {
  164. return current;
  165. }
  166. if (candidate.IsAssignableFrom(current))
  167. {
  168. return candidate;
  169. }
  170. if (IsNumberOrBool(current) && IsNumberOrBool(candidate))
  171. {
  172. return GetPromotedNumberType(current, candidate);
  173. }
  174. if (IsCallableType(current) && IsCallableType(candidate))
  175. {
  176. return ICallableType;
  177. }
  178. if (current.IsClass && candidate.IsClass)
  179. {
  180. if (current == ObjectType || candidate == ObjectType)
  181. {
  182. return ObjectType;
  183. }
  184. if (current.GetTypeDepth() < candidate.GetTypeDepth())
  185. {
  186. return GetMostGenericType(current.BaseType, candidate);
  187. }
  188. return GetMostGenericType(current, candidate.BaseType);
  189. }
  190. return ObjectType;
  191. }
  192. public IType GetPromotedNumberType(IType left, IType right)
  193. {
  194. if (left == DecimalType ||
  195. right == DecimalType)
  196. {
  197. return DecimalType;
  198. }
  199. if (left == DoubleType ||
  200. right == DoubleType)
  201. {
  202. return DoubleType;
  203. }
  204. if (left == SingleType ||
  205. right == SingleType)
  206. {
  207. return SingleType;
  208. }
  209. if (left == ULongType)
  210. {
  211. if (right == SByteType ||
  212. right == ShortType ||
  213. right == IntType ||
  214. right == LongType)
  215. {
  216. // This is against the C# spec but allows expressions like:
  217. // ulong x = 4
  218. // y = x + 1
  219. // y will be long.
  220. // C# disallows mixing ulongs and signed numbers
  221. // but in the above case it promotes the constant to ulong
  222. // and the result is ulong.
  223. // Since its too late here to promote the constant,
  224. // maybe we should return LongType. I didn't chose ULongType
  225. // because in other cases <unsigned> <op> <signed> returns <signed>.
  226. return LongType;
  227. }
  228. return ULongType;
  229. }
  230. if (right == ULongType)
  231. {
  232. if (left == SByteType ||
  233. left == ShortType ||
  234. left == IntType ||
  235. left == LongType)
  236. {
  237. // This is against the C# spec but allows expressions like:
  238. // ulong x = 4
  239. // y = 1 + x
  240. // y will be long.
  241. // C# disallows mixing ulongs and signed numbers
  242. // but in the above case it promotes the constant to ulong
  243. // and the result is ulong.
  244. // Since its too late here to promote the constant,
  245. // maybe we should return LongType. I didn't chose ULongType
  246. // because in other cases <signed> <op> <unsigned> returns <signed>.
  247. return LongType;
  248. }
  249. return ULongType;
  250. }
  251. if (left == LongType ||
  252. right == LongType)
  253. {
  254. return LongType;
  255. }
  256. if (left == UIntType)
  257. {
  258. if (right == SByteType ||
  259. right == ShortType ||
  260. right == IntType)
  261. {
  262. // This is allowed per C# spec and y is long:
  263. // uint x = 4
  264. // y = x + 1
  265. // C# promotes <uint> <op> <signed> to <long> also
  266. // but in the above case it promotes the constant to uint first
  267. // and the result of "x + 1" is uint.
  268. // Since its too late here to promote the constant,
  269. // "y = x + 1" will be long in boo.
  270. return LongType;
  271. }
  272. return UIntType;
  273. }
  274. if (right == UIntType)
  275. {
  276. if (left == SByteType ||
  277. left == ShortType ||
  278. left == IntType)
  279. {
  280. // This is allowed per C# spec and y is long:
  281. // uint x = 4
  282. // y = 1 + x
  283. // C# promotes <signed> <op> <uint> to <long> also
  284. // but in the above case it promotes the constant to uint first
  285. // and the result of "1 + x" is uint.
  286. // Since its too late here to promote the constant,
  287. // "y = x + 1" will be long in boo.
  288. return LongType;
  289. }
  290. return UIntType;
  291. }
  292. if (left == IntType ||
  293. right == IntType ||
  294. left == ShortType ||
  295. right == ShortType ||
  296. left == UShortType ||
  297. right == UShortType ||
  298. left == ByteType ||
  299. right == ByteType ||
  300. left == SByteType ||
  301. right == SByteType)
  302. {
  303. return IntType;
  304. }
  305. return left;
  306. }
  307. public static bool IsReadOnlyField(IField field)
  308. {
  309. return field.IsInitOnly || field.IsLiteral;
  310. }
  311. public bool IsCallable(IType type)
  312. {
  313. return (TypeType == type) || IsCallableType(type) || IsDuckType(type);
  314. }
  315. public virtual bool IsDuckTyped(Expression expression)
  316. {
  317. IType type = expression.ExpressionType;
  318. return null != type && this.IsDuckType(type);
  319. }
  320. public bool IsQuackBuiltin(Expression node)
  321. {
  322. return IsQuackBuiltin(GetOptionalEntity(node));
  323. }
  324. public bool IsQuackBuiltin(IEntity entity)
  325. {
  326. return BuiltinFunction.Quack == entity;
  327. }
  328. public bool IsDuckType(IType type)
  329. {
  330. if (null == type)
  331. {
  332. throw new ArgumentNullException("type");
  333. }
  334. return (
  335. (type == DuckType)
  336. || KnowsQuackFu(type)
  337. || (_context.Parameters.Ducky
  338. && (type == ObjectType)));
  339. }
  340. public bool KnowsQuackFu(IType type)
  341. {
  342. return type.IsSubclassOf(IQuackFuType);
  343. }
  344. bool IsCallableType(IType type)
  345. {
  346. return (ICallableType.IsAssignableFrom(type)) || (type is ICallableType);
  347. }
  348. public AnonymousCallableType GetCallableType(IMethod method)
  349. {
  350. CallableSignature signature = new CallableSignature(method);
  351. return GetCallableType(signature);
  352. }
  353. public AnonymousCallableType GetCallableType(CallableSignature signature)
  354. {
  355. return _anonymousCallablesManager.GetCallableType(signature);
  356. }
  357. public virtual IType GetConcreteCallableType(Node sourceNode, CallableSignature signature)
  358. {
  359. return _anonymousCallablesManager.GetConcreteCallableType(sourceNode, signature);
  360. }
  361. public virtual IType GetConcreteCallableType(Node sourceNode, AnonymousCallableType anonymousType)
  362. {
  363. return _anonymousCallablesManager.GetConcreteCallableType(sourceNode, anonymousType);
  364. }
  365. public IType GetEnumeratorItemType(IType iteratorType)
  366. {
  367. // Arrays are enumerators of their element type
  368. if (iteratorType.IsArray) return iteratorType.GetElementType();
  369. // String are enumerators of char
  370. if (StringType == iteratorType) return CharType;
  371. // Try to use an EnumerableItemType attribute
  372. if (iteratorType.IsClass)
  373. {
  374. IType enumeratorItemType = GetEnumeratorItemTypeFromAttribute(iteratorType);
  375. if (null != enumeratorItemType) return enumeratorItemType;
  376. }
  377. // Try to use a generic IEnumerable interface
  378. IType genericItemType = GetGenericEnumerableItemType(iteratorType);
  379. if (null != genericItemType) return genericItemType;
  380. // If none of these work, the type is an enumerator of object
  381. return ObjectType;
  382. }
  383. public IType GetExpressionType(Expression node)
  384. {
  385. IType type = node.ExpressionType;
  386. if (null == type)
  387. {
  388. throw CompilerErrorFactory.InvalidNode(node);
  389. }
  390. return type;
  391. }
  392. public IType GetConcreteExpressionType(Expression expression)
  393. {
  394. IType type = GetExpressionType(expression);
  395. AnonymousCallableType anonymousType = type as AnonymousCallableType;
  396. if (null != anonymousType)
  397. {
  398. IType concreteType = GetConcreteCallableType(expression, anonymousType);
  399. expression.ExpressionType = concreteType;
  400. return concreteType;
  401. }
  402. return type;
  403. }
  404. public void MapToConcreteExpressionTypes(ExpressionCollection items)
  405. {
  406. foreach (Expression item in items)
  407. {
  408. GetConcreteExpressionType(item);
  409. }
  410. }
  411. public ClassDefinition GetCompilerGeneratedExtensionsClass()
  412. {
  413. if (null == _compilerGeneratedExtensionsClass)
  414. {
  415. BooClassBuilder builder = CodeBuilder.CreateClass("CompilerGeneratedExtensions");
  416. builder.Modifiers = TypeMemberModifiers.Final|TypeMemberModifiers.Transient|TypeMemberModifiers.Public;
  417. builder.AddBaseType(ObjectType);
  418. BooMethodBuilder ctor = builder.AddConstructor();
  419. ctor.Modifiers = TypeMemberModifiers.Private;
  420. ctor.Body.Add(
  421. CodeBuilder.CreateSuperConstructorInvocation(ObjectType));
  422. ClassDefinition cd = builder.ClassDefinition;
  423. Module module = GetCompilerGeneratedExtensionsModule();
  424. module.Members.Add(cd);
  425. ((ModuleEntity)module.Entity).InitializeModuleClass(cd);
  426. _compilerGeneratedExtensionsClass = cd;
  427. }
  428. return _compilerGeneratedExtensionsClass;
  429. }
  430. public Module GetCompilerGeneratedExtensionsModule()
  431. {
  432. if (null == _compilerGeneratedExtensionsModule)
  433. {
  434. _compilerGeneratedExtensionsModule = NewModule(null, "CompilerGeneratedExtensions");
  435. }
  436. return _compilerGeneratedExtensionsModule;
  437. }
  438. public void AddCompilerGeneratedType(TypeDefinition type)
  439. {
  440. GetCompilerGeneratedTypesModule().Members.Add(type);
  441. }
  442. public Module GetCompilerGeneratedTypesModule()
  443. {
  444. if (null == _compilerGeneratedTypesModule)
  445. {
  446. _compilerGeneratedTypesModule = NewModule("CompilerGenerated");
  447. }
  448. return _compilerGeneratedTypesModule;
  449. }
  450. private Module NewModule(string nameSpace)
  451. {
  452. return NewModule(nameSpace, nameSpace);
  453. }
  454. private Module NewModule(string nameSpace, string moduleName)
  455. {
  456. Module module = new Module();
  457. module.Name = moduleName;
  458. if (null != nameSpace) module.Namespace = new NamespaceDeclaration(nameSpace);
  459. module.Entity = new ModuleEntity(_context.NameResolutionService, this, module);
  460. _context.CompileUnit.Modules.Add(module);
  461. return module;
  462. }
  463. public ClassDefinition CreateCallableDefinition(string name)
  464. {
  465. ClassDefinition cd = new ClassDefinition();
  466. cd.IsSynthetic = true;
  467. cd.BaseTypes.Add(CodeBuilder.CreateTypeReference(this.MulticastDelegateType));
  468. cd.BaseTypes.Add(CodeBuilder.CreateTypeReference(this.ICallableType));
  469. cd.Name = name;
  470. cd.Modifiers = TypeMemberModifiers.Final;
  471. cd.Members.Add(CreateCallableConstructor());
  472. cd.Members.Add(CreateCallMethod());
  473. cd.Entity = new InternalCallableType(this, cd);
  474. return cd;
  475. }
  476. Method CreateCallMethod()
  477. {
  478. Method method = new Method("Call");
  479. method.IsSynthetic = true;
  480. method.Modifiers = TypeMemberModifiers.Public|TypeMemberModifiers.Virtual;
  481. method.Parameters.Add(CodeBuilder.CreateParameterDeclaration(1, "args", ObjectArrayType));
  482. method.ReturnType = CodeBuilder.CreateTypeReference(ObjectType);
  483. method.Entity = new InternalMethod(this, method);
  484. return method;
  485. }
  486. Constructor CreateCallableConstructor()
  487. {
  488. Constructor constructor = new Constructor();
  489. constructor.IsSynthetic = true;
  490. constructor.Modifiers = TypeMemberModifiers.Public;
  491. constructor.ImplementationFlags = MethodImplementationFlags.Runtime;
  492. constructor.Parameters.Add(
  493. CodeBuilder.CreateParameterDeclaration(1, "instance", ObjectType));
  494. constructor.Parameters.Add(
  495. CodeBuilder.CreateParameterDeclaration(2, "method", IntPtrType));
  496. constructor.Entity = new InternalConstructor(this, constructor);
  497. return constructor;
  498. }
  499. public bool AreTypesRelated(IType lhs, IType rhs)
  500. {
  501. ICallableType ctype = lhs as ICallableType;
  502. if (null != ctype)
  503. {
  504. return ctype.IsAssignableFrom(rhs)
  505. || ctype.IsSubclassOf(rhs);
  506. }
  507. return lhs.IsAssignableFrom(rhs)
  508. || (lhs.IsInterface && !rhs.IsFinal)
  509. || (rhs.IsInterface && !lhs.IsFinal)
  510. || CanBeReachedByDownCastOrPromotion(lhs, rhs)
  511. || FindImplicitConversionOperator(rhs,lhs) != null;
  512. }
  513. public IMethod FindExplicitConversionOperator(IType fromType, IType toType)
  514. {
  515. return FindConversionOperator("op_Explicit", fromType, toType);
  516. }
  517. public IMethod FindImplicitConversionOperator(IType fromType, IType toType)
  518. {
  519. return FindConversionOperator("op_Implicit", fromType, toType);
  520. }
  521. public IMethod FindConversionOperator(string name, IType fromType, IType toType)
  522. {
  523. while (fromType != this.ObjectType)
  524. {
  525. IMethod method = FindConversionOperator(name, fromType, toType, fromType.GetMembers());
  526. if (null != method) return method;
  527. method = FindConversionOperator(name, fromType, toType, toType.GetMembers());
  528. if (null != method) return method;
  529. method = FindConversionOperator(name, fromType, toType, FindExtension(fromType, name));
  530. if (null != method) return method;
  531. fromType = fromType.BaseType;
  532. if (null == fromType) break;
  533. }
  534. return null;
  535. }
  536. private IEntity[] FindExtension(IType fromType, string name)
  537. {
  538. IEntity extension = _context.NameResolutionService.ResolveExtension(fromType, name);
  539. if (null == extension) return Ambiguous.NoEntities;
  540. Ambiguous a = extension as Ambiguous;
  541. if (null != a) return a.Entities;
  542. return new IEntity[] { extension };
  543. }
  544. IMethod FindConversionOperator(string name, IType fromType, IType toType, IEntity[] candidates)
  545. {
  546. foreach (IEntity entity in candidates)
  547. {
  548. if (EntityType.Method != entity.EntityType || name != entity.Name) continue;
  549. IMethod method = (IMethod)entity;
  550. if (IsConversionOperator(method, fromType, toType)) return method;
  551. }
  552. return null;
  553. }
  554. bool IsConversionOperator(IMethod method, IType fromType, IType toType)
  555. {
  556. if (!method.IsStatic) return false;
  557. if (method.ReturnType != toType) return false;
  558. IParameter[] parameters = method.GetParameters();
  559. return (1 == parameters.Length && fromType == parameters[0].Type);
  560. }
  561. public bool IsCallableTypeAssignableFrom(ICallableType lhs, IType rhs)
  562. {
  563. if (lhs == rhs) return true;
  564. if (Null.Default == rhs) return true;
  565. ICallableType other = rhs as ICallableType;
  566. if (null == other) return false;
  567. CallableSignature lvalue = lhs.GetSignature();
  568. CallableSignature rvalue = other.GetSignature();
  569. if (lvalue == rvalue) return true;
  570. IParameter[] lparams = lvalue.Parameters;
  571. IParameter[] rparams = rvalue.Parameters;
  572. if (lparams.Length < rparams.Length) return false;
  573. for (int i=0; i<rparams.Length; ++i)
  574. {
  575. if (!AreTypesRelated(lparams[i].Type, rparams[i].Type)) return false;
  576. }
  577. return CompatibleReturnTypes(lvalue, rvalue);
  578. }
  579. private bool CompatibleReturnTypes(CallableSignature lvalue, CallableSignature rvalue)
  580. {
  581. if (VoidType != lvalue.ReturnType && VoidType != rvalue.ReturnType)
  582. {
  583. return AreTypesRelated(lvalue.ReturnType, rvalue.ReturnType);
  584. }
  585. return true;
  586. }
  587. public static bool CheckOverrideSignature(IMethod impl, IMethod baseMethod)
  588. {
  589. if (!GenericsServices.AreOfSameGenerity(impl, baseMethod))
  590. {
  591. return false;
  592. }
  593. CallableSignature baseSignature = GetOverriddenSignature(baseMethod, impl);
  594. return CheckOverrideSignature(impl.GetParameters(), baseSignature.Parameters);
  595. }
  596. public static bool CheckOverrideSignature(IParameter[] implParameters, IParameter[] baseParameters)
  597. {
  598. return CallableSignature.AreSameParameters(implParameters, baseParameters);
  599. }
  600. public static CallableSignature GetOverriddenSignature(IMethod baseMethod, IMethod impl)
  601. {
  602. if (baseMethod.GenericInfo != null && TypeSystem.GenericsServices.AreOfSameGenerity(baseMethod, impl))
  603. {
  604. return baseMethod.GenericInfo.ConstructMethod(impl.GenericInfo.GenericParameters).CallableType.GetSignature();
  605. }
  606. return baseMethod.CallableType.GetSignature();
  607. }
  608. public virtual bool CanBeReachedByDownCastOrPromotion(IType expectedType, IType actualType)
  609. {
  610. return CanBeReachedByDowncast(expectedType, actualType)
  611. || CanBeReachedByPromotion(expectedType, actualType);
  612. }
  613. public virtual bool CanBeReachedByDowncast(IType expectedType, IType actualType)
  614. {
  615. return actualType.IsAssignableFrom(expectedType);
  616. }
  617. public virtual bool CanBeReachedByPromotion(IType expectedType, IType actualType)
  618. {
  619. return (expectedType.IsValueType
  620. && IsNumber(expectedType)
  621. && IsNumber(actualType));
  622. }
  623. public bool CanBeExplicitlyCastToInteger(IType type)
  624. {
  625. return type.IsEnum || type == this.CharType;
  626. }
  627. public static bool ContainsMethodsOnly(List members)
  628. {
  629. foreach (IEntity member in members)
  630. {
  631. if (EntityType.Method != member.EntityType) return false;
  632. }
  633. return true;
  634. }
  635. public bool IsIntegerNumber(IType type)
  636. {
  637. return
  638. type == this.ShortType ||
  639. type == this.IntType ||
  640. type == this.LongType ||
  641. type == this.SByteType ||
  642. type == this.UShortType ||
  643. type == this.UIntType ||
  644. type == this.ULongType ||
  645. type == this.ByteType;
  646. }
  647. public bool IsIntegerOrBool(IType type)
  648. {
  649. return BoolType == type || IsIntegerNumber(type);
  650. }
  651. public bool IsNumberOrBool(IType type)
  652. {
  653. return BoolType == type || IsNumber(type);
  654. }
  655. public bool IsNumber(IType type)
  656. {
  657. return
  658. IsPrimitiveNumber(type) ||
  659. type == this.DecimalType;
  660. }
  661. public bool IsPrimitiveNumber(IType type)
  662. {
  663. return
  664. IsIntegerNumber(type) ||
  665. type == this.DoubleType ||
  666. type == this.SingleType;
  667. }
  668. public static bool IsNullable(IType type)
  669. {
  670. ExternalType et = type as ExternalType;
  671. return (null != et && et.ActualType.IsGenericType && et.ActualType.GetGenericTypeDefinition() == Types.Nullable);
  672. }
  673. public IType GetNullableUnderlyingType(IType type)
  674. {
  675. ExternalType et = type as ExternalType;
  676. return Map(Nullable.GetUnderlyingType(et.ActualType));
  677. }
  678. public static bool IsUnknown(Expression node)
  679. {
  680. IType type = node.ExpressionType;
  681. if (null != type)
  682. {
  683. return IsUnknown(type);
  684. }
  685. return false;
  686. }
  687. public static bool IsUnknown(IType tag)
  688. {
  689. return EntityType.Unknown == tag.EntityType;
  690. }
  691. public static bool IsError(Expression node)
  692. {
  693. IType type = node.ExpressionType;
  694. if (null != type)
  695. {
  696. return IsError(type);
  697. }
  698. return false;
  699. }
  700. public static bool IsErrorAny(ExpressionCollection collection)
  701. {
  702. foreach (Expression n in collection)
  703. {
  704. if (IsError(n))
  705. {
  706. return true;
  707. }
  708. }
  709. return false;
  710. }
  711. public bool IsBuiltin(IEntity tag)
  712. {
  713. if (EntityType.Method == tag.EntityType)
  714. {
  715. return BuiltinsType == ((IMethod)tag).DeclaringType;
  716. }
  717. return false;
  718. }
  719. public static bool IsError(IEntity tag)
  720. {
  721. return EntityType.Error == tag.EntityType;
  722. }
  723. public static TypeMemberModifiers GetAccess(IAccessibleMember member)
  724. {
  725. if (member.IsPublic)
  726. {
  727. return TypeMemberModifiers.Public;
  728. }
  729. else if (member.IsProtected)
  730. {
  731. return TypeMemberModifiers.Protected;
  732. }
  733. return TypeMemberModifiers.Private;
  734. }
  735. public static IEntity[] GetAllMembers(INamespace entity)
  736. {
  737. List members = new List();
  738. GetAllMembers(members, entity);
  739. return (IEntity[])members.ToArray(new IEntity[members.Count]);
  740. }
  741. private static void GetAllMembers(List members, INamespace entity)
  742. {
  743. if (null == entity) return;
  744. IType type = entity as IType;
  745. if (null != type)
  746. {
  747. members.ExtendUnique(type.GetMembers());
  748. GetAllMembers(members, type.BaseType);
  749. }
  750. else
  751. {
  752. members.Extend(entity.GetMembers());
  753. }
  754. }
  755. static object EntityAnnotationKey = new object();
  756. public static void Bind(Node node, IEntity entity)
  757. {
  758. if (null == node) throw new ArgumentNullException("node");
  759. node[EntityAnnotationKey] = entity;
  760. }
  761. public static IEntity GetOptionalEntity(Node node)
  762. {
  763. if (null == node) throw new ArgumentNullException("node");
  764. return (IEntity)node[EntityAnnotationKey];
  765. }
  766. public static IEntity GetEntity(Node node)
  767. {
  768. IEntity tag = GetOptionalEntity(node);
  769. if (null == tag) InvalidNode(node);
  770. return tag;
  771. }
  772. public static IType GetReferencedType(Expression typeref)
  773. {
  774. switch (typeref.NodeType)
  775. {
  776. case NodeType.TypeofExpression:
  777. {
  778. return GetType(((TypeofExpression)typeref).Type);
  779. }
  780. case NodeType.ReferenceExpression:
  781. case NodeType.MemberReferenceExpression:
  782. case NodeType.GenericReferenceExpression:
  783. {
  784. return typeref.Entity as IType;
  785. }
  786. }
  787. return null;
  788. }
  789. public virtual bool IsModule(Type type)
  790. {
  791. return type.IsClass
  792. && type.IsSealed
  793. && !type.IsNestedPublic
  794. && MetadataUtil.IsAttributeDefined(type, Types.ModuleAttribute);
  795. }
  796. public bool IsAttribute(IType type)
  797. {
  798. return type.IsSubclassOf(SystemAttribute);
  799. }
  800. public static IType GetType(Node node)
  801. {
  802. return ((ITypedEntity)GetEntity(node)).Type;
  803. }
  804. public IType Map(Type type)
  805. {
  806. ExternalType entity = (ExternalType)_entityCache[type];
  807. if (null == entity)
  808. {
  809. if (type.IsArray) return GetArrayType(Map(type.GetElementType()), type.GetArrayRank());
  810. entity = CreateEntityForType(type);
  811. Cache(entity);
  812. }
  813. return entity;
  814. }
  815. private ExternalType CreateEntityForType(Type type)
  816. {
  817. if (type.IsGenericParameter) return new ExternalGenericParameter(this, type);
  818. if (type.IsSubclassOf(Types.MulticastDelegate)) return new ExternalCallableType(this, type);
  819. return new ExternalType(this, type);
  820. }
  821. public IArrayType GetArrayType(IType elementType, int rank)
  822. {
  823. ArrayHash key = new ArrayHash(elementType, rank);
  824. IArrayType entity = (IArrayType)_arrayCache[key];
  825. if (null == entity)
  826. {
  827. entity = new ArrayType(this, elementType, rank);
  828. _arrayCache.Add(key, entity);
  829. }
  830. return entity;
  831. }
  832. protected class ArrayHash
  833. {
  834. IType _type;
  835. int _rank;
  836. public ArrayHash(IType elementType, int rank)
  837. {
  838. _type = elementType;
  839. _rank = rank;
  840. }
  841. public override int GetHashCode()
  842. {
  843. return _type.GetHashCode() ^ _rank;
  844. }
  845. public override bool Equals(object obj)
  846. {
  847. return ((ArrayHash)obj)._type == _type && ((ArrayHash)obj)._rank == _rank;
  848. }
  849. }
  850. public IParameter[] Map(ParameterDeclarationCollection parameters)
  851. {
  852. IParameter[] mapped = new IParameter[parameters.Count];
  853. for (int i=0; i<mapped.Length; ++i)
  854. {
  855. mapped[i] = (IParameter)GetEntity(parameters[i]);
  856. }
  857. return mapped;
  858. }
  859. public IParameter[] Map(ParameterInfo[] parameters)
  860. {
  861. IParameter[] mapped = new IParameter[parameters.Length];
  862. for (int i=0; i<parameters.Length; ++i)
  863. {
  864. mapped[i] = new ExternalParameter(this, parameters[i]);
  865. }
  866. return mapped;
  867. }
  868. public IConstructor Map(ConstructorInfo constructor)
  869. {
  870. object key = GetCacheKey(constructor);
  871. IConstructor entity = (IConstructor)_entityCache[key];
  872. if (null == entity)
  873. {
  874. entity = new ExternalConstructor(this, constructor);
  875. _entityCache[key] = entity;
  876. }
  877. return entity;
  878. }
  879. public IMethod Map(MethodInfo method)
  880. {
  881. object key = GetCacheKey(method);
  882. IMethod entity = (IMethod)_entityCache[key];
  883. if (null == entity)
  884. {
  885. entity = new ExternalMethod(this, method);
  886. _entityCache[key] = entity;
  887. }
  888. return entity;
  889. }
  890. public IEntity Map(MemberInfo[] info)
  891. {
  892. if (info.Length > 1)
  893. {
  894. IEntity[] tags = new IEntity[info.Length];
  895. for (int i=0; i<tags.Length; ++i)
  896. {
  897. tags[i] = Map(info[i]);
  898. }
  899. return new Ambiguous(tags);
  900. }
  901. if (info.Length > 0)
  902. {
  903. return Map(info[0]);
  904. }
  905. return null;
  906. }
  907. public IEntity Map(MemberInfo mi)
  908. {
  909. IEntity tag = (IEntity)_entityCache[GetCacheKey(mi)];
  910. if (null == tag)
  911. {
  912. switch (mi.MemberType)
  913. {
  914. case MemberTypes.Method:
  915. {
  916. return Map((MethodInfo)mi);
  917. }
  918. case MemberTypes.Constructor:
  919. {
  920. return Map((ConstructorInfo)mi);
  921. }
  922. case MemberTypes.Field:
  923. {
  924. tag = new ExternalField(this, (FieldInfo)mi);
  925. break;
  926. }
  927. case MemberTypes.Property:
  928. {
  929. tag = new ExternalProperty(this, (PropertyInfo)mi);
  930. break;
  931. }
  932. case MemberTypes.Event:
  933. {
  934. tag = new ExternalEvent(this, (EventInfo)mi);
  935. break;
  936. }
  937. case MemberTypes.NestedType:
  938. {
  939. return Map((Type)mi);
  940. }
  941. default:
  942. {
  943. throw new NotImplementedException(mi.ToString());
  944. }
  945. }
  946. _entityCache.Add(GetCacheKey(mi), tag);
  947. }
  948. return tag;
  949. }
  950. public string GetSignature(IEntityWithParameters method)
  951. {
  952. return GetSignature(method, true);
  953. }
  954. public string GetSignature(IEntityWithParameters method, bool includeFullName)
  955. {
  956. _buffer.Length = 0;
  957. if (includeFullName)
  958. {
  959. _buffer.Append(method.FullName);
  960. }
  961. else
  962. {
  963. _buffer.Append(method.Name);
  964. }
  965. _buffer.Append("(");
  966. IParameter[] parameters = method.GetParameters();
  967. for (int i=0; i<parameters.Length; ++i)
  968. {
  969. if (i > 0) { _buffer.Append(", "); }
  970. if (method.AcceptVarArgs && i == parameters.Length-1) { _buffer.Append('*'); }
  971. _buffer.Append(parameters[i].Type);
  972. }
  973. _buffer.Append(")");
  974. return _buffer.ToString();
  975. }
  976. public object GetCacheKey(MemberInfo mi)
  977. {
  978. return mi;
  979. }
  980. public IEntity ResolvePrimitive(string name)
  981. {
  982. return (IEntity)_primitives[name];
  983. }
  984. public bool IsPrimitive(string name)
  985. {
  986. return _primitives.ContainsKey(name);
  987. }
  988. /// <summary>
  989. /// checks if the passed type will be equivalente to
  990. /// System.Object in runtime (accounting for the presence
  991. /// of duck typing).
  992. /// </summary>
  993. public bool IsSystemObject(IType type)
  994. {
  995. return type == ObjectType || type == DuckType;
  996. }
  997. public bool RequiresBoxing(IType expectedType, IType actualType)
  998. {
  999. if (!actualType.IsValueType) return false;
  1000. return IsSystemObject(expectedType);
  1001. }
  1002. protected virtual void PreparePrimitives()
  1003. {
  1004. AddPrimitiveType("duck", DuckType);
  1005. AddPrimitiveType("void", VoidType);
  1006. AddPrimitiveType("object", ObjectType);
  1007. AddPrimitiveType("bool", BoolType);
  1008. AddPrimitiveType("sbyte", SByteType);
  1009. AddPrimitiveType("byte", ByteType);
  1010. AddPrimitiveType("short", ShortType);
  1011. AddPrimitiveType("ushort", UShortType);
  1012. AddPrimitiveType("int", IntType);
  1013. AddPrimitiveType("uint", UIntType);
  1014. AddPrimitiveType("long", LongType);
  1015. AddPrimitiveType("ulong", ULongType);
  1016. AddPrimitiveType("single", SingleType);
  1017. AddPrimitiveType("double", DoubleType);
  1018. AddPrimitiveType("decimal", DecimalType);
  1019. AddPrimitiveType("char", CharType);
  1020. AddPrimitiveType("string", StringType);
  1021. AddPrimitiveType("regex", RegexType);
  1022. AddPrimitiveType("date", DateTimeType);
  1023. AddPrimitiveType("timespan", TimeSpanType);
  1024. AddPrimitiveType("callable", ICallableType);
  1025. }
  1026. protected virtual void PrepareBuiltinFunctions()
  1027. {
  1028. AddBuiltin(BuiltinFunction.Len);
  1029. AddBuiltin(BuiltinFunction.AddressOf);
  1030. AddBuiltin(BuiltinFunction.Eval);
  1031. AddBuiltin(BuiltinFunction.Switch);
  1032. }
  1033. protected void AddPrimitiveType(string name, ExternalType type)
  1034. {
  1035. _primitives[name] = type;
  1036. type.PrimitiveName = name;
  1037. }
  1038. protected void AddBuiltin(BuiltinFunction function)
  1039. {
  1040. _primitives[function.Name] = function;
  1041. }
  1042. protected void Cache(ExternalType tag)
  1043. {
  1044. _entityCache[tag.ActualType] = tag;
  1045. }
  1046. protected void Cache(object key, IType tag)
  1047. {
  1048. _entityCache[key] = tag;
  1049. }
  1050. public IConstructor GetDefaultConstructor(IType type)
  1051. {
  1052. IConstructor[] constructors = type.GetConstructors();
  1053. for (int i=0; i<constructors.Length; ++i)
  1054. {
  1055. IConstructor constructor = constructors[i];
  1056. if (0 == constructor.GetParameters().Length)
  1057. {
  1058. return constructor;
  1059. }
  1060. }
  1061. return null;
  1062. }
  1063. IType GetExternalEnumeratorItemType(IType iteratorType)
  1064. {
  1065. Type type = ((ExternalType)iteratorType).ActualType;
  1066. EnumeratorItemTypeAttribute attribute = (EnumeratorItemTypeAttribute)System.Attribute.GetCustomAttribute(type, typeof(EnumeratorItemTypeAttribute));
  1067. if (null != attribute)
  1068. {
  1069. return Map(attribute.ItemType);
  1070. }
  1071. return null;
  1072. }
  1073. IType GetEnumeratorItemTypeFromAttribute(IType iteratorType)
  1074. {
  1075. // If iterator type is external get its attributes via reflection
  1076. if (iteratorType is ExternalType)
  1077. {
  1078. return GetExternalEnumeratorItemType(iteratorType);
  1079. }
  1080. // If iterator type is a generic constructed type, map its attribute from its definition
  1081. GenericConstructedType constructedType = iteratorType as GenericConstructedType;
  1082. if (constructedType != null)
  1083. {
  1084. return constructedType.GenericMapping.Map(
  1085. GetEnumeratorItemTypeFromAttribute(constructedType.GenericDefinition));
  1086. }
  1087. // If iterator type is internal get its attributes from its type definition
  1088. AbstractInternalType internalType = (AbstractInternalType)iteratorType;
  1089. IType enumeratorItemTypeAttribute = Map(typeof(EnumeratorItemTypeAttribute));
  1090. foreach (Attribute attribute in internalType.TypeDefinition.Attributes)
  1091. {
  1092. IConstructor constructor = GetEntity(attribute) as IConstructor;
  1093. if (null != constructor)
  1094. {
  1095. if (constructor.DeclaringType == enumeratorItemTypeAttribute)
  1096. {
  1097. return GetType(attribute.Arguments[0]);
  1098. }
  1099. }
  1100. }
  1101. return null;
  1102. }
  1103. public IType GetGenericEnumerableItemType(IType iteratorType)
  1104. {
  1105. // Arrays implicitly implement IEnumerable[of element type]
  1106. if (iteratorType is ArrayType) return iteratorType.GetElementType();
  1107. // If type is not an array, try to find IEnumerable[of some type] in its interfaces
  1108. IType itemType = null;
  1109. foreach (IType type in GenericsServices.FindConstructedTypes(iteratorType, IEnumerableGenericType))
  1110. {
  1111. IType candidateItemType = type.ConstructedInfo.GenericArguments[0];
  1112. if (itemType != null)
  1113. {
  1114. itemType = GetMostGenericType(itemType, candidateItemType);
  1115. }
  1116. else
  1117. {
  1118. itemType = candidateItemType;
  1119. }
  1120. }
  1121. return itemType;
  1122. }
  1123. public IEntity GetMemberEntity(TypeMember member)
  1124. {
  1125. if (null == member.Entity)
  1126. {
  1127. member.Entity = CreateEntity(member);
  1128. }
  1129. return member.Entity;
  1130. }
  1131. private IEntity CreateEntity(TypeMember member)
  1132. {
  1133. switch (member.NodeType)
  1134. {
  1135. case NodeType.ClassDefinition:
  1136. return new InternalClass(this, (TypeDefinition) member);
  1137. case NodeType.Field:
  1138. return new InternalField((Field)member);
  1139. case NodeType.EnumMember:
  1140. return new InternalEnumMember(this, (EnumMember)member);
  1141. case NodeType.Method:
  1142. return new InternalMethod(this, (Method)member);
  1143. case NodeType.Constructor:
  1144. return new InternalConstructor(this, (Constructor)member);
  1145. case NodeType.Property:
  1146. return new InternalProperty(this, (Property)member);
  1147. case NodeType.Event:
  1148. return new InternalEvent(this, (Event)member);
  1149. }
  1150. throw new ArgumentException("Member type not supported: " + member);
  1151. }
  1152. private static void InvalidNode(Node node)
  1153. {
  1154. throw CompilerErrorFactory.InvalidNode(node);
  1155. }
  1156. public class DuckTypeImpl : ExternalType
  1157. {
  1158. public DuckTypeImpl(TypeSystemServices typeSystemServices) :
  1159. base(typeSystemServices, Types.Object)
  1160. {
  1161. }
  1162. }
  1163. #region VoidTypeImpl
  1164. class VoidTypeImpl : ExternalType
  1165. {
  1166. internal VoidTypeImpl(TypeSystemServices typeSystemServices) : base(typeSystemServices, Types.Void)
  1167. {
  1168. }
  1169. override public bool Resolve(List targetList, string name, EntityType flags)
  1170. {
  1171. return false;
  1172. }
  1173. override public bool IsSubclassOf(IType other)
  1174. {
  1175. return false;
  1176. }
  1177. override public bool IsAssignableFrom(IType other)
  1178. {
  1179. return false;
  1180. }
  1181. }
  1182. #endregion
  1183. public virtual IType ExceptionType
  1184. {
  1185. get { return Map(typeof(Exception)); }
  1186. }
  1187. public virtual bool IsValidException(IType type)
  1188. {
  1189. return ExceptionType.IsAssignableFrom(type);
  1190. }
  1191. public virtual IConstructor GetStringExceptionConstructor()
  1192. {
  1193. return Map(typeof(Exception).GetConstructor(new Type[] { typeof(string) }));
  1194. }
  1195. }
  1196. }