PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/w4x/boolangstudio
C# | 1395 lines | 1108 code | 211 blank | 76 comment | 252 complexity | 4a0247aabff6dd1adafe0478b176ff2a 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. return GenericsServices.AreOfSameGenerity(impl, baseMethod)
  590. && CheckOverrideSignature(impl.GetParameters(), baseMethod.GetParameters());
  591. }
  592. public static bool CheckOverrideSignature(IParameter[] implParameters, IParameter[] baseParameters)
  593. {
  594. return CallableSignature.AreSameParameters(implParameters, baseParameters);
  595. }
  596. public virtual bool CanBeReachedByDownCastOrPromotion(IType expectedType, IType actualType)
  597. {
  598. return CanBeReachedByDowncast(expectedType, actualType)
  599. || CanBeReachedByPromotion(expectedType, actualType);
  600. }
  601. public virtual bool CanBeReachedByDowncast(IType expectedType, IType actualType)
  602. {
  603. return actualType.IsAssignableFrom(expectedType);
  604. }
  605. public virtual bool CanBeReachedByPromotion(IType expectedType, IType actualType)
  606. {
  607. return (expectedType.IsValueType
  608. && IsNumber(expectedType)
  609. && IsNumber(actualType));
  610. }
  611. public bool CanBeExplicitlyCastToInteger(IType type)
  612. {
  613. return type.IsEnum || type == this.CharType;
  614. }
  615. public static bool ContainsMethodsOnly(List members)
  616. {
  617. foreach (IEntity member in members)
  618. {
  619. if (EntityType.Method != member.EntityType) return false;
  620. }
  621. return true;
  622. }
  623. public bool IsIntegerNumber(IType type)
  624. {
  625. return
  626. type == this.ShortType ||
  627. type == this.IntType ||
  628. type == this.LongType ||
  629. type == this.SByteType ||
  630. type == this.UShortType ||
  631. type == this.UIntType ||
  632. type == this.ULongType ||
  633. type == this.ByteType;
  634. }
  635. public bool IsIntegerOrBool(IType type)
  636. {
  637. return BoolType == type || IsIntegerNumber(type);
  638. }
  639. public bool IsNumberOrBool(IType type)
  640. {
  641. return BoolType == type || IsNumber(type);
  642. }
  643. public bool IsNumber(IType type)
  644. {
  645. return
  646. IsPrimitiveNumber(type) ||
  647. type == this.DecimalType;
  648. }
  649. public bool IsPrimitiveNumber(IType type)
  650. {
  651. return
  652. IsIntegerNumber(type) ||
  653. type == this.DoubleType ||
  654. type == this.SingleType;
  655. }
  656. public static bool IsNullable(IType type)
  657. {
  658. ExternalType et = type as ExternalType;
  659. return (null != et && et.ActualType.IsGenericType && et.ActualType.GetGenericTypeDefinition() == Types.Nullable);
  660. }
  661. public IType GetNullableUnderlyingType(IType type)
  662. {
  663. ExternalType et = type as ExternalType;
  664. return Map(Nullable.GetUnderlyingType(et.ActualType));
  665. }
  666. public static bool IsUnknown(Expression node)
  667. {
  668. IType type = node.ExpressionType;
  669. if (null != type)
  670. {
  671. return IsUnknown(type);
  672. }
  673. return false;
  674. }
  675. public static bool IsUnknown(IType tag)
  676. {
  677. return EntityType.Unknown == tag.EntityType;
  678. }
  679. public static bool IsError(Expression node)
  680. {
  681. IType type = node.ExpressionType;
  682. if (null != type)
  683. {
  684. return IsError(type);
  685. }
  686. return false;
  687. }
  688. public static bool IsErrorAny(ExpressionCollection collection)
  689. {
  690. foreach (Expression n in collection)
  691. {
  692. if (IsError(n))
  693. {
  694. return true;
  695. }
  696. }
  697. return false;
  698. }
  699. public bool IsBuiltin(IEntity tag)
  700. {
  701. if (EntityType.Method == tag.EntityType)
  702. {
  703. return BuiltinsType == ((IMethod)tag).DeclaringType;
  704. }
  705. return false;
  706. }
  707. public static bool IsError(IEntity tag)
  708. {
  709. return EntityType.Error == tag.EntityType;
  710. }
  711. public static TypeMemberModifiers GetAccess(IAccessibleMember member)
  712. {
  713. if (member.IsPublic)
  714. {
  715. return TypeMemberModifiers.Public;
  716. }
  717. else if (member.IsProtected)
  718. {
  719. return TypeMemberModifiers.Protected;
  720. }
  721. return TypeMemberModifiers.Private;
  722. }
  723. public static IEntity[] GetAllMembers(INamespace entity)
  724. {
  725. List members = new List();
  726. GetAllMembers(members, entity);
  727. return (IEntity[])members.ToArray(new IEntity[members.Count]);
  728. }
  729. private static void GetAllMembers(List members, INamespace entity)
  730. {
  731. if (null == entity) return;
  732. IType type = entity as IType;
  733. if (null != type)
  734. {
  735. members.ExtendUnique(type.GetMembers());
  736. GetAllMembers(members, type.BaseType);
  737. }
  738. else
  739. {
  740. members.Extend(entity.GetMembers());
  741. }
  742. }
  743. static object EntityAnnotationKey = new object();
  744. public static void Bind(Node node, IEntity entity)
  745. {
  746. if (null == node) throw new ArgumentNullException("node");
  747. node[EntityAnnotationKey] = entity;
  748. }
  749. public static IEntity GetOptionalEntity(Node node)
  750. {
  751. if (null == node) throw new ArgumentNullException("node");
  752. return (IEntity)node[EntityAnnotationKey];
  753. }
  754. public static IEntity GetEntity(Node node)
  755. {
  756. IEntity tag = GetOptionalEntity(node);
  757. if (null == tag) InvalidNode(node);
  758. return tag;
  759. }
  760. public static IType GetReferencedType(Expression typeref)
  761. {
  762. switch (typeref.NodeType)
  763. {
  764. case NodeType.TypeofExpression:
  765. {
  766. return GetType(((TypeofExpression)typeref).Type);
  767. }
  768. case NodeType.ReferenceExpression:
  769. case NodeType.MemberReferenceExpression:
  770. case NodeType.GenericReferenceExpression:
  771. {
  772. return typeref.Entity as IType;
  773. }
  774. }
  775. return null;
  776. }
  777. public virtual bool IsModule(Type type)
  778. {
  779. return type.IsClass
  780. && type.IsSealed
  781. && !type.IsNestedPublic
  782. && MetadataUtil.IsAttributeDefined(type, Types.ModuleAttribute);
  783. }
  784. public bool IsAttribute(IType type)
  785. {
  786. return type.IsSubclassOf(SystemAttribute);
  787. }
  788. public static IType GetType(Node node)
  789. {
  790. return ((ITypedEntity)GetEntity(node)).Type;
  791. }
  792. public IType Map(Type type)
  793. {
  794. ExternalType entity = (ExternalType)_entityCache[type];
  795. if (null == entity)
  796. {
  797. if (type.IsArray) return GetArrayType(Map(type.GetElementType()), type.GetArrayRank());
  798. entity = CreateEntityForType(type);
  799. Cache(entity);
  800. }
  801. return entity;
  802. }
  803. private ExternalType CreateEntityForType(Type type)
  804. {
  805. if (type.IsGenericParameter) return new ExternalGenericParameter(this, type);
  806. if (type.IsSubclassOf(Types.MulticastDelegate)) return new ExternalCallableType(this, type);
  807. return new ExternalType(this, type);
  808. }
  809. public IArrayType GetArrayType(IType elementType, int rank)
  810. {
  811. ArrayHash key = new ArrayHash(elementType, rank);
  812. IArrayType entity = (IArrayType)_arrayCache[key];
  813. if (null == entity)
  814. {
  815. entity = new ArrayType(this, elementType, rank);
  816. _arrayCache.Add(key, entity);
  817. }
  818. return entity;
  819. }
  820. protected class ArrayHash
  821. {
  822. IType _type;
  823. int _rank;
  824. public ArrayHash(IType elementType, int rank)
  825. {
  826. _type = elementType;
  827. _rank = rank;
  828. }
  829. public override int GetHashCode()
  830. {
  831. return _type.GetHashCode() ^ _rank;
  832. }
  833. public override bool Equals(object obj)
  834. {
  835. return ((ArrayHash)obj)._type == _type && ((ArrayHash)obj)._rank == _rank;
  836. }
  837. }
  838. public IParameter[] Map(ParameterDeclarationCollection parameters)
  839. {
  840. IParameter[] mapped = new IParameter[parameters.Count];
  841. for (int i=0; i<mapped.Length; ++i)
  842. {
  843. mapped[i] = (IParameter)GetEntity(parameters[i]);
  844. }
  845. return mapped;
  846. }
  847. public IParameter[] Map(ParameterInfo[] parameters)
  848. {
  849. IParameter[] mapped = new IParameter[parameters.Length];
  850. for (int i=0; i<parameters.Length; ++i)
  851. {
  852. mapped[i] = new ExternalParameter(this, parameters[i]);
  853. }
  854. return mapped;
  855. }
  856. public IConstructor Map(ConstructorInfo constructor)
  857. {
  858. object key = GetCacheKey(constructor);
  859. IConstructor entity = (IConstructor)_entityCache[key];
  860. if (null == entity)
  861. {
  862. entity = new ExternalConstructor(this, constructor);
  863. _entityCache[key] = entity;
  864. }
  865. return entity;
  866. }
  867. public IMethod Map(MethodInfo method)
  868. {
  869. object key = GetCacheKey(method);
  870. IMethod entity = (IMethod)_entityCache[key];
  871. if (null == entity)
  872. {
  873. entity = new ExternalMethod(this, method);
  874. _entityCache[key] = entity;
  875. }
  876. return entity;
  877. }
  878. public IEntity Map(MemberInfo[] info)
  879. {
  880. if (info.Length > 1)
  881. {
  882. IEntity[] tags = new IEntity[info.Length];
  883. for (int i=0; i<tags.Length; ++i)
  884. {
  885. tags[i] = Map(info[i]);
  886. }
  887. return new Ambiguous(tags);
  888. }
  889. if (info.Length > 0)
  890. {
  891. return Map(info[0]);
  892. }
  893. return null;
  894. }
  895. public IEntity Map(MemberInfo mi)
  896. {
  897. IEntity tag = (IEntity)_entityCache[GetCacheKey(mi)];
  898. if (null == tag)
  899. {
  900. switch (mi.MemberType)
  901. {
  902. case MemberTypes.Method:
  903. {
  904. return Map((MethodInfo)mi);
  905. }
  906. case MemberTypes.Constructor:
  907. {
  908. return Map((ConstructorInfo)mi);
  909. }
  910. case MemberTypes.Field:
  911. {
  912. tag = new ExternalField(this, (FieldInfo)mi);
  913. break;
  914. }
  915. case MemberTypes.Property:
  916. {
  917. tag = new ExternalProperty(this, (PropertyInfo)mi);
  918. break;
  919. }
  920. case MemberTypes.Event:
  921. {
  922. tag = new ExternalEvent(this, (EventInfo)mi);
  923. break;
  924. }
  925. case MemberTypes.NestedType:
  926. {
  927. return Map((Type)mi);
  928. }
  929. default:
  930. {
  931. throw new NotImplementedException(mi.ToString());
  932. }
  933. }
  934. _entityCache.Add(GetCacheKey(mi), tag);
  935. }
  936. return tag;
  937. }
  938. public string GetSignature(IEntityWithParameters method)
  939. {
  940. return GetSignature(method, true);
  941. }
  942. public string GetSignature(IEntityWithParameters method, bool includeFullName)
  943. {
  944. _buffer.Length = 0;
  945. if (includeFullName)
  946. {
  947. _buffer.Append(method.FullName);
  948. }
  949. else
  950. {
  951. _buffer.Append(method.Name);
  952. }
  953. _buffer.Append("(");
  954. IParameter[] parameters = method.GetParameters();
  955. for (int i=0; i<parameters.Length; ++i)
  956. {
  957. if (i > 0) { _buffer.Append(", "); }
  958. if (method.AcceptVarArgs && i == parameters.Length-1) { _buffer.Append('*'); }
  959. _buffer.Append(parameters[i].Type);
  960. }
  961. _buffer.Append(")");
  962. return _buffer.ToString();
  963. }
  964. public object GetCacheKey(MemberInfo mi)
  965. {
  966. return mi;
  967. }
  968. public IEntity ResolvePrimitive(string name)
  969. {
  970. return (IEntity)_primitives[name];
  971. }
  972. public bool IsPrimitive(string name)
  973. {
  974. return _primitives.ContainsKey(name);
  975. }
  976. /// <summary>
  977. /// checks if the passed type will be equivalente to
  978. /// System.Object in runtime (accounting for the presence
  979. /// of duck typing).
  980. /// </summary>
  981. public bool IsSystemObject(IType type)
  982. {
  983. return type == ObjectType || type == DuckType;
  984. }
  985. public bool RequiresBoxing(IType expectedType, IType actualType)
  986. {
  987. if (!actualType.IsValueType) return false;
  988. return IsSystemObject(expectedType);
  989. }
  990. protected virtual void PreparePrimitives()
  991. {
  992. AddPrimitiveType("duck", DuckType);
  993. AddPrimitiveType("void", VoidType);
  994. AddPrimitiveType("object", ObjectType);
  995. AddPrimitiveType("bool", BoolType);
  996. AddPrimitiveType("sbyte", SByteType);
  997. AddPrimitiveType("byte", ByteType);
  998. AddPrimitiveType("short", ShortType);
  999. AddPrimitiveType("ushort", UShortType);
  1000. AddPrimitiveType("int", IntType);
  1001. AddPrimitiveType("uint", UIntType);
  1002. AddPrimitiveType("long", LongType);
  1003. AddPrimitiveType("ulong", ULongType);
  1004. AddPrimitiveType("single", SingleType);
  1005. AddPrimitiveType("double", DoubleType);
  1006. AddPrimitiveType("decimal", DecimalType);
  1007. AddPrimitiveType("char", CharType);
  1008. AddPrimitiveType("string", StringType);
  1009. AddPrimitiveType("regex", RegexType);
  1010. AddPrimitiveType("date", DateTimeType);
  1011. AddPrimitiveType("timespan", TimeSpanType);
  1012. AddPrimitiveType("callable", ICallableType);
  1013. }
  1014. protected virtual void PrepareBuiltinFunctions()
  1015. {
  1016. AddBuiltin(BuiltinFunction.Len);
  1017. AddBuiltin(BuiltinFunction.AddressOf);
  1018. AddBuiltin(BuiltinFunction.Eval);
  1019. AddBuiltin(BuiltinFunction.Switch);
  1020. }
  1021. protected void AddPrimitiveType(string name, ExternalType type)
  1022. {
  1023. _primitives[name] = type;
  1024. type.PrimitiveName = name;
  1025. }
  1026. protected void AddBuiltin(BuiltinFunction function)
  1027. {
  1028. _primitives[function.Name] = function;
  1029. }
  1030. protected void Cache(ExternalType tag)
  1031. {
  1032. _entityCache[tag.ActualType] = tag;
  1033. }
  1034. protected void Cache(object key, IType tag)
  1035. {
  1036. _entityCache[key] = tag;
  1037. }
  1038. public IConstructor GetDefaultConstructor(IType type)
  1039. {
  1040. IConstructor[] constructors = type.GetConstructors();
  1041. for (int i=0; i<constructors.Length; ++i)
  1042. {
  1043. IConstructor constructor = constructors[i];
  1044. if (0 == constructor.GetParameters().Length)
  1045. {
  1046. return constructor;
  1047. }
  1048. }
  1049. return null;
  1050. }
  1051. IType GetExternalEnumeratorItemType(IType iteratorType)
  1052. {
  1053. Type type = ((ExternalType)iteratorType).ActualType;
  1054. EnumeratorItemTypeAttribute attribute = (EnumeratorItemTypeAttribute)System.Attribute.GetCustomAttribute(type, typeof(EnumeratorItemTypeAttribute));
  1055. if (null != attribute)
  1056. {
  1057. return Map(attribute.ItemType);
  1058. }
  1059. return null;
  1060. }
  1061. IType GetEnumeratorItemTypeFromAttribute(IType iteratorType)
  1062. {
  1063. // If iterator type is external get its attributes via reflection
  1064. if (iteratorType is ExternalType)
  1065. {
  1066. return GetExternalEnumeratorItemType(iteratorType);
  1067. }
  1068. // If iterator type is a generic constructed type, map its attribute from its definition
  1069. GenericConstructedType constructedType = iteratorType as GenericConstructedType;
  1070. if (constructedType != null)
  1071. {
  1072. return constructedType.GenericMapping.Map(
  1073. GetEnumeratorItemTypeFromAttribute(constructedType.GenericDefinition));
  1074. }
  1075. // If iterator type is internal get its attributes from its type definition
  1076. AbstractInternalType internalType = (AbstractInternalType)iteratorType;
  1077. IType enumeratorItemTypeAttribute = Map(typeof(EnumeratorItemTypeAttribute));
  1078. foreach (Attribute attribute in internalType.TypeDefinition.Attributes)
  1079. {
  1080. IConstructor constructor = GetEntity(attribute) as IConstructor;
  1081. if (null != constructor)
  1082. {
  1083. if (constructor.DeclaringType == enumeratorItemTypeAttribute)
  1084. {
  1085. return GetType(attribute.Arguments[0]);
  1086. }
  1087. }
  1088. }
  1089. return null;
  1090. }
  1091. public IType GetGenericEnumerableItemType(IType iteratorType)
  1092. {
  1093. // Arrays implicitly implement IEnumerable[of element type]
  1094. if (iteratorType is ArrayType) return iteratorType.GetElementType();
  1095. // If type is not an array, try to find IEnumerable[of some type] in its interfaces
  1096. IType itemType = null;
  1097. foreach (IType type in GenericsServices.FindConstructedTypes(iteratorType, IEnumerableGenericType))
  1098. {
  1099. IType candidateItemType = type.ConstructedInfo.GenericArguments[0];
  1100. if (itemType != null)
  1101. {
  1102. itemType = GetMostGenericType(itemType, candidateItemType);
  1103. }
  1104. else
  1105. {
  1106. itemType = candidateItemType;
  1107. }
  1108. }
  1109. return itemType;
  1110. }
  1111. public IEntity GetMemberEntity(TypeMember member)
  1112. {
  1113. if (null == member.Entity)
  1114. {
  1115. member.Entity = CreateEntity(member);
  1116. }
  1117. return member.Entity;
  1118. }
  1119. private IEntity CreateEntity(TypeMember member)
  1120. {
  1121. switch (member.NodeType)
  1122. {
  1123. case NodeType.ClassDefinition:
  1124. return new InternalClass(this, (TypeDefinition) member);
  1125. case NodeType.Field:
  1126. return new InternalField((Field)member);
  1127. case NodeType.EnumMember:
  1128. return new InternalEnumMember(this, (EnumMember)member);
  1129. case NodeType.Method:
  1130. return new InternalMethod(this, (Method)member);
  1131. case NodeType.Constructor:
  1132. return new InternalConstructor(this, (Constructor)member);
  1133. case NodeType.Property:
  1134. return new InternalProperty(this, (Property)member);
  1135. case NodeType.Event:
  1136. return new InternalEvent(this, (Event)member);
  1137. }
  1138. throw new ArgumentException("Member type not supported: " + member);
  1139. }
  1140. private static void InvalidNode(Node node)
  1141. {
  1142. throw CompilerErrorFactory.InvalidNode(node);
  1143. }
  1144. public class DuckTypeImpl : ExternalType
  1145. {
  1146. public DuckTypeImpl(TypeSystemServices typeSystemServices) :
  1147. base(typeSystemServices, Types.Object)
  1148. {
  1149. }
  1150. }
  1151. #region VoidTypeImpl
  1152. class VoidTypeImpl : ExternalType
  1153. {
  1154. internal VoidTypeImpl(TypeSystemServices typeSystemServices) : base(typeSystemServices, Types.Void)
  1155. {
  1156. }
  1157. override public bool Resolve(List targetList, string name, EntityType flags)
  1158. {
  1159. return false;
  1160. }
  1161. override public bool IsSubclassOf(IType other)
  1162. {
  1163. return false;
  1164. }
  1165. override public bool IsAssignableFrom(IType other)
  1166. {
  1167. return false;
  1168. }
  1169. }
  1170. #endregion
  1171. public virtual IType ExceptionType
  1172. {
  1173. get { return Map(typeof(Exception)); }
  1174. }
  1175. public virtual bool IsValidException(IType type)
  1176. {
  1177. return ExceptionType.IsAssignableFrom(type);
  1178. }
  1179. public virtual IConstructor GetStringExceptionConstructor()
  1180. {
  1181. return Map(typeof(Exception).GetConstructor(new Type[] { typeof(string) }));
  1182. }
  1183. }
  1184. }