PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs

http://github.com/bamboo/boo
C# | 5994 lines | 5017 code | 851 blank | 126 comment | 1047 complexity | c81e3259365c03049891a150beb9d223 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  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. using System;
  29. using System.Collections;
  30. using System.Collections.Generic;
  31. using System.Diagnostics;
  32. using System.IO;
  33. using System.Linq;
  34. using System.Reflection;
  35. using System.Text;
  36. using Boo.Lang.Compiler.Ast;
  37. using Boo.Lang.Compiler.Ast.Visitors;
  38. using Boo.Lang.Compiler.Steps.Generators;
  39. using Boo.Lang.Compiler.TypeSystem;
  40. using Boo.Lang.Compiler.TypeSystem.Core;
  41. using Boo.Lang.Compiler.TypeSystem.Generics;
  42. using Boo.Lang.Compiler.TypeSystem.Internal;
  43. using Boo.Lang.Compiler.TypeSystem.Reflection;
  44. using Boo.Lang.Compiler.TypeSystem.Services;
  45. using Boo.Lang.Environments;
  46. using Boo.Lang.Runtime;
  47. using Attribute = Boo.Lang.Compiler.Ast.Attribute;
  48. using Module = Boo.Lang.Compiler.Ast.Module;
  49. namespace Boo.Lang.Compiler.Steps
  50. {
  51. /// <summary>
  52. /// AST semantic evaluation.
  53. /// </summary>
  54. public class ProcessMethodBodies : AbstractNamespaceSensitiveVisitorCompilerStep, ITypeMemberReifier
  55. {
  56. static readonly ExpressionCollection EmptyExpressionCollection = new ExpressionCollection();
  57. static readonly object OptionalReturnStatementAnnotation = new object();
  58. static readonly object ResolvedAsExtensionAnnotation = new object();
  59. private Stack<InternalMethod> _methodStack;
  60. private Stack _memberStack;
  61. // for accurate error reporting during type inference
  62. private Module _currentModule;
  63. private InternalMethod _currentMethod;
  64. private bool _optimizeNullComparisons = true;
  65. const string TempInitializerName = "$___temp_initializer";
  66. public override void Initialize(CompilerContext context)
  67. {
  68. base.Initialize(context);
  69. _currentModule = null;
  70. _currentMethod = null;
  71. _methodStack = new Stack<InternalMethod>();
  72. _memberStack = new Stack();
  73. _callableResolutionService = new EnvironmentProvision<CallableResolutionService>();
  74. _invocationTypeReferenceRules = new EnvironmentProvision<InvocationTypeInferenceRules>();
  75. _typeChecker = new EnvironmentProvision<TypeChecker>();
  76. _methodCache = new EnvironmentProvision<RuntimeMethodCache>();
  77. }
  78. override public void Run()
  79. {
  80. NameResolutionService.Reset();
  81. Visit(CompileUnit);
  82. }
  83. override public void Dispose()
  84. {
  85. base.Dispose();
  86. _currentModule = null;
  87. _currentMethod = null;
  88. _methodStack = null;
  89. _memberStack = null;
  90. }
  91. protected CallableResolutionService CallableResolutionService
  92. {
  93. get { return _callableResolutionService; }
  94. }
  95. private EnvironmentProvision<CallableResolutionService> _callableResolutionService;
  96. protected IMethod ResolveMethod(IType type, string name)
  97. {
  98. return NameResolutionService.ResolveMethod(type, name);
  99. }
  100. protected IProperty ResolveProperty(IType type, string name)
  101. {
  102. return NameResolutionService.ResolveProperty(type, name);
  103. }
  104. override public void OnModule(Module module)
  105. {
  106. if (WasVisited(module))
  107. return;
  108. MarkVisited(module);
  109. _currentModule = module;
  110. EnterNamespace(InternalModule.ScopeFor(module));
  111. Visit(module.Members);
  112. Visit(module.AssemblyAttributes);
  113. LeaveNamespace();
  114. }
  115. override public void OnInterfaceDefinition(InterfaceDefinition node)
  116. {
  117. if (WasVisited(node)) return;
  118. MarkVisited(node);
  119. VisitTypeDefinition(node);
  120. }
  121. private void VisitBaseTypes(TypeDefinition node)
  122. {
  123. foreach (var baseTypeRef in node.BaseTypes)
  124. EnsureRelatedNodeWasVisited(baseTypeRef, baseTypeRef.Entity);
  125. }
  126. private void VisitTypeDefinition(TypeDefinition node)
  127. {
  128. var ns = (INamespace)GetEntity(node);
  129. EnterNamespace(ns);
  130. VisitBaseTypes(node);
  131. Visit(node.Attributes);
  132. Visit(node.Members);
  133. LeaveNamespace();
  134. }
  135. override public void OnClassDefinition(ClassDefinition node)
  136. {
  137. if (WasVisited(node))
  138. return;
  139. MarkVisited(node);
  140. VisitTypeDefinition(node);
  141. FlushFieldInitializers(node);
  142. }
  143. void FlushFieldInitializers(ClassDefinition node)
  144. {
  145. foreach (TypeMember member in node.Members.ToArray())
  146. {
  147. switch (member.NodeType)
  148. {
  149. case NodeType.Field:
  150. ProcessFieldInitializer((Field) member);
  151. break;
  152. case NodeType.StatementTypeMember:
  153. ProcessStatementTypeMemberInitializer(node, ((StatementTypeMember)member));
  154. break;
  155. }
  156. }
  157. var initializer = (Method) node["$initializer$"];
  158. if (null != initializer)
  159. {
  160. AddInitializerToInstanceConstructors(node, initializer);
  161. node.Members.Remove(initializer);
  162. }
  163. }
  164. private void ProcessStatementTypeMemberInitializer(ClassDefinition node, StatementTypeMember statementTypeMember)
  165. {
  166. var stmt = statementTypeMember.Statement;
  167. var initializer = GetInitializerFor(node, node.IsStatic);
  168. initializer.Body.Add(stmt);
  169. var entity = (InternalMethod) GetEntity(initializer);
  170. ProcessNodeInMethodContext(entity, entity, stmt);
  171. node.Members.Remove(statementTypeMember);
  172. }
  173. override public void OnAttribute(Attribute node)
  174. {
  175. var tag = node.Entity as IType;
  176. if (null != tag && !IsError(tag))
  177. {
  178. Visit(node.Arguments);
  179. ResolveNamedArguments(tag, node.NamedArguments);
  180. IConstructor constructor = GetCorrectConstructor(node, tag, node.Arguments);
  181. if (null != constructor)
  182. {
  183. Bind(node, constructor);
  184. }
  185. }
  186. }
  187. private static bool IsError(IEntity entity)
  188. {
  189. return TypeSystemServices.IsError(entity);
  190. }
  191. override public void OnProperty(Property node)
  192. {
  193. if (WasVisited(node))
  194. return;
  195. MarkVisited(node);
  196. Visit(node.Attributes);
  197. Visit(node.Type);
  198. Visit(node.Parameters);
  199. ResolvePropertyOverride(node);
  200. ProcessGetter(node);
  201. if (node.Type == null)
  202. node.Type = CodeBuilder.CreateTypeReference(node.LexicalInfo, InferTypeOfProperty(node));
  203. if (node.Getter != null)
  204. node.Getter.ReturnType = node.Type.CloneNode();
  205. ProcessSetter(node);
  206. }
  207. private void ProcessSetter(Property node)
  208. {
  209. if (node.Setter != null)
  210. {
  211. NormalizeSetterOf(node);
  212. Visit(node.Setter);
  213. }
  214. }
  215. private void ProcessGetter(Property node)
  216. {
  217. if (node.Getter != null)
  218. {
  219. NormalizeGetterOf(node);
  220. Visit(node.Getter);
  221. }
  222. }
  223. private static void NormalizeGetterOf(Property node)
  224. {
  225. node.Getter.Parameters.ExtendWithClones(node.Parameters);
  226. if (node.Getter.ReturnType == null && node.Type != null)
  227. node.Getter.ReturnType = node.Type.CloneNode();
  228. }
  229. private IType InferTypeOfProperty(Property node)
  230. {
  231. if (node.Getter == null)
  232. return TypeSystemServices.ObjectType;
  233. var getterType = GetEntity(node.Getter).ReturnType;
  234. if (getterType != TypeSystemServices.VoidType)
  235. return getterType;
  236. return TypeSystemServices.ObjectType;
  237. }
  238. private void NormalizeSetterOf(Property node)
  239. {
  240. var setter = node.Setter;
  241. setter.Name = "set_" + node.Name;
  242. var setterParameters = setter.Parameters;
  243. setterParameters.ExtendWithClones(node.Parameters);
  244. setterParameters.Add(CodeBuilder.CreateParameterDeclaration(CodeBuilder.GetFirstParameterIndex(setter) + setterParameters.Count, "value", GetType(node.Type)));
  245. }
  246. override public void OnStatementTypeMember(StatementTypeMember node)
  247. {
  248. // statement type members are later
  249. // processed as initializers
  250. }
  251. override public void OnField(Field node)
  252. {
  253. if (WasVisited(node))
  254. return;
  255. MarkVisited(node);
  256. var entity = (InternalField)GetEntity(node);
  257. Visit(node.Attributes);
  258. Visit(node.Type);
  259. if (node.Initializer != null)
  260. {
  261. var type = (null != node.Type) ? GetType(node.Type) : null;
  262. if (null != type && TypeSystemServices.IsNullable(type))
  263. BindNullableInitializer(node, node.Initializer, type);
  264. if (entity.DeclaringType.IsValueType && !node.IsStatic)
  265. Error(CompilerErrorFactory.ValueTypeFieldsCannotHaveInitializers(node.Initializer));
  266. try
  267. {
  268. PushMember(node);
  269. PreProcessFieldInitializer(node);
  270. }
  271. finally
  272. {
  273. PopMember();
  274. }
  275. }
  276. else
  277. {
  278. if (null == node.Type)
  279. {
  280. node.Type = CreateTypeReference(node.LexicalInfo, TypeSystemServices.ObjectType);
  281. }
  282. }
  283. CheckFieldType(node.Type);
  284. }
  285. static bool IsValidLiteralInitializer(Expression e)
  286. {
  287. switch (e.NodeType)
  288. {
  289. case NodeType.BoolLiteralExpression:
  290. case NodeType.IntegerLiteralExpression:
  291. case NodeType.DoubleLiteralExpression:
  292. case NodeType.NullLiteralExpression:
  293. case NodeType.StringLiteralExpression:
  294. return true;
  295. }
  296. return false;
  297. }
  298. void ProcessLiteralField(Field node)
  299. {
  300. Visit(node.Initializer);
  301. ProcessFieldInitializerType(node, node.Initializer.ExpressionType);
  302. ((InternalField)node.Entity).StaticValue = node.Initializer;
  303. node.Initializer = null;
  304. }
  305. void ProcessFieldInitializerType(Field node, IType initializerType)
  306. {
  307. if (null == node.Type)
  308. node.Type = CreateTypeReference(node.LexicalInfo, MapWildcardType(initializerType));
  309. else
  310. AssertTypeCompatibility(node.Initializer, GetType(node.Type), initializerType);
  311. }
  312. private TypeReference CreateTypeReference(LexicalInfo info, IType type)
  313. {
  314. var reference = CodeBuilder.CreateTypeReference(type);
  315. reference.LexicalInfo = info;
  316. return reference;
  317. }
  318. private void PreProcessFieldInitializer(Field node)
  319. {
  320. Expression initializer = node.Initializer;
  321. if (node.IsFinal && node.IsStatic)
  322. {
  323. if (IsValidLiteralInitializer(initializer))
  324. {
  325. ProcessLiteralField(node);
  326. return;
  327. }
  328. }
  329. BlockExpression closure = node.Initializer as BlockExpression;
  330. if (closure != null)
  331. {
  332. InferClosureSignature(closure);
  333. }
  334. Method method = GetInitializerMethod(node);
  335. InternalMethod entity = (InternalMethod)method.Entity;
  336. ReferenceExpression temp = new ReferenceExpression(TempInitializerName);
  337. BinaryExpression assignment = new BinaryExpression(
  338. node.LexicalInfo,
  339. BinaryOperatorType.Assign,
  340. temp,
  341. initializer);
  342. ProcessNodeInMethodContext(entity, entity, assignment);
  343. method.Locals.RemoveByEntity(temp.Entity);
  344. IType initializerType = GetExpressionType(assignment.Right);
  345. ProcessFieldInitializerType(node, initializerType);
  346. node.Initializer = assignment.Right;
  347. }
  348. void ProcessFieldInitializer(Field node)
  349. {
  350. Expression initializer = node.Initializer;
  351. if (null == initializer) return;
  352. //do not unnecessarily assign fields to default values
  353. switch (initializer.NodeType)
  354. {
  355. case NodeType.NullLiteralExpression:
  356. node.Initializer = null;
  357. return;
  358. case NodeType.IntegerLiteralExpression:
  359. if (0 == ((IntegerLiteralExpression) initializer).Value) {
  360. node.Initializer = null;
  361. return;
  362. }
  363. break;
  364. case NodeType.BoolLiteralExpression:
  365. if (false == ((BoolLiteralExpression) initializer).Value) {
  366. node.Initializer = null;
  367. return;
  368. }
  369. break;
  370. case NodeType.DoubleLiteralExpression:
  371. if (0.0f == ((DoubleLiteralExpression) initializer).Value) {
  372. node.Initializer = null;
  373. return;
  374. }
  375. break;
  376. }
  377. Method method = GetInitializerMethod(node);
  378. method.Body.Add(
  379. CodeBuilder.CreateAssignment(
  380. initializer.LexicalInfo,
  381. CodeBuilder.CreateReference(node),
  382. initializer));
  383. node.Initializer = null;
  384. }
  385. Method CreateInitializerMethod(TypeDefinition type, string name, TypeMemberModifiers modifiers)
  386. {
  387. Method method = CodeBuilder.CreateMethod(name, TypeSystemServices.VoidType, modifiers);
  388. type.Members.Add(method);
  389. MarkVisited(method);
  390. return method;
  391. }
  392. private Field GetFieldsInitializerInitializedField(TypeDefinition type)
  393. {
  394. string name = AstUtil.BuildUniqueTypeMemberName(type, "initialized");
  395. Field field= (Field) type.Members[name];
  396. if (null == field)
  397. {
  398. field = CodeBuilder.CreateField(name, TypeSystemServices.BoolType);
  399. field.Visibility = TypeMemberModifiers.Private;
  400. type.Members.Add(field);
  401. MarkVisited(field);
  402. }
  403. return field;
  404. }
  405. Method GetInitializerMethod(Field node)
  406. {
  407. return GetInitializerFor(node.DeclaringType, node.IsStatic);
  408. }
  409. private Method GetInitializerFor(TypeDefinition type, bool isStatic)
  410. {
  411. string methodName = isStatic ? "$static_initializer$" : "$initializer$";
  412. Method method = (Method)type[methodName];
  413. if (null == method)
  414. {
  415. if (isStatic)
  416. {
  417. if (!type.HasStaticConstructor)
  418. {
  419. // when the class doesnt have a static constructor
  420. // yet, create one and use it as the static
  421. // field initializer method
  422. method = CodeBuilder.CreateStaticConstructor(type);
  423. }
  424. else
  425. {
  426. method = CreateInitializerMethod(type, methodName, TypeMemberModifiers.Static);
  427. AddInitializerToStaticConstructor(type, (InternalMethod)method.Entity);
  428. }
  429. }
  430. else
  431. {
  432. method = CreateInitializerMethod(type, methodName, TypeMemberModifiers.None);
  433. }
  434. type[methodName] = method;
  435. }
  436. return method;
  437. }
  438. void AddInitializerToStaticConstructor(TypeDefinition type, InternalMethod initializer)
  439. {
  440. GetStaticConstructor(type).Body.Insert(0,
  441. CodeBuilder.CreateMethodInvocation(initializer));
  442. }
  443. void AddInitializerToInstanceConstructors(TypeDefinition type, Method initializer)
  444. {
  445. int n = 0;
  446. //count number of non-static constructors
  447. foreach (TypeMember node in type.Members)
  448. {
  449. if (NodeType.Constructor == node.NodeType && !node.IsStatic)
  450. n++;
  451. }
  452. //if there is more than one we need $initialized$ guard check
  453. if (n > 1)
  454. AddInitializedGuardToInitializer(type, initializer);
  455. foreach (TypeMember node in type.Members)
  456. {
  457. if (NodeType.Constructor == node.NodeType && !node.IsStatic)
  458. {
  459. Constructor constructor = (Constructor) node;
  460. n = GetIndexAfterSuperInvocation(constructor.Body);
  461. foreach (Statement st in initializer.Body.Statements)
  462. {
  463. constructor.Body.Insert(n, (Statement) st.Clone());
  464. n++;
  465. }
  466. foreach (Local loc in initializer.Locals)
  467. {
  468. constructor.Locals.Add(loc);
  469. }
  470. }
  471. }
  472. }
  473. void AddInitializedGuardToInitializer(TypeDefinition type, Method initializer)
  474. {
  475. Field field = GetFieldsInitializerInitializedField(type);
  476. //run initializer code only if $initialized$ is false
  477. //hmm quasi-notation would be lovely here
  478. Block trueBlock = new Block();
  479. trueBlock.Add(new GotoStatement(LexicalInfo.Empty, new ReferenceExpression("___initialized___")));
  480. IfStatement cond = new IfStatement(CodeBuilder.CreateReference(field),
  481. trueBlock, null);
  482. initializer.Body.Insert(0, cond);
  483. //set $initialized$ field to true
  484. initializer.Body.Add(
  485. CodeBuilder.CreateFieldAssignment(field, new BoolLiteralExpression(true)));
  486. //label we're past the initializer
  487. initializer.Body.Add(
  488. new LabelStatement(LexicalInfo.Empty, "___initialized___"));
  489. }
  490. int GetIndexAfterSuperInvocation(Block body)
  491. {
  492. int index = 0;
  493. foreach (Statement s in body.Statements)
  494. {
  495. if (NodeType.ExpressionStatement == s.NodeType)
  496. {
  497. Expression expression = ((ExpressionStatement)s).Expression;
  498. if (NodeType.MethodInvocationExpression == expression.NodeType)
  499. {
  500. if (NodeType.SuperLiteralExpression == ((MethodInvocationExpression)expression).Target.NodeType)
  501. {
  502. return index + 1;
  503. }
  504. }
  505. }
  506. ++index;
  507. }
  508. return 0;
  509. }
  510. Constructor GetStaticConstructor(TypeDefinition type)
  511. {
  512. return CodeBuilder.GetOrCreateStaticConstructorFor(type);
  513. }
  514. void CheckRuntimeMethod(Method method)
  515. {
  516. if (method.Body.IsEmpty) return;
  517. Error(CompilerErrorFactory.RuntimeMethodBodyMustBeEmpty(method, GetEntity(method)));
  518. }
  519. //ECMA-335 Partition III Section 1.8.1.4
  520. //cannot call an instance method before super/self.
  521. void CheckInstanceMethodInvocationsWithinConstructor(Constructor ctor)
  522. {
  523. if (ctor.Body.IsEmpty)
  524. return;
  525. foreach (Statement st in ctor.Body.Statements)
  526. {
  527. ExpressionStatement est = st as ExpressionStatement;
  528. if (null == est) continue;
  529. MethodInvocationExpression mie = est.Expression as MethodInvocationExpression;
  530. if (null == mie) continue;
  531. if (mie.Target is SelfLiteralExpression
  532. || mie.Target is SuperLiteralExpression)
  533. break;//okay we're done checking
  534. if (mie.Target is MemberReferenceExpression)
  535. {
  536. MemberReferenceExpression mre = (MemberReferenceExpression) mie.Target;
  537. if (mre.Target is SelfLiteralExpression
  538. || mre.Target is SuperLiteralExpression)
  539. {
  540. Error(CompilerErrorFactory.InstanceMethodInvocationBeforeInitialization(ctor, mre));
  541. }
  542. }
  543. }
  544. }
  545. override public void OnConstructor(Constructor node)
  546. {
  547. if (WasVisited(node))
  548. {
  549. return;
  550. }
  551. MarkVisited(node);
  552. Visit(node.Attributes);
  553. Visit(node.Parameters);
  554. InternalConstructor entity = (InternalConstructor)node.Entity;
  555. ProcessMethodBody(entity);
  556. if (node.IsRuntime)
  557. {
  558. CheckRuntimeMethod(node);
  559. }
  560. else
  561. {
  562. if (entity.DeclaringType.IsValueType)
  563. {
  564. if (0 == node.Parameters.Count
  565. && !node.IsStatic
  566. && !node.IsSynthetic)
  567. {
  568. Error(CompilerErrorFactory.ValueTypesCannotDeclareParameterlessConstructors(node));
  569. }
  570. }
  571. else if (
  572. !entity.HasSelfCall &&
  573. !entity.HasSuperCall &&
  574. !entity.IsStatic)
  575. {
  576. IType baseType = entity.DeclaringType.BaseType;
  577. IConstructor super = GetCorrectConstructor(node, baseType, EmptyExpressionCollection);
  578. if (null != super)
  579. {
  580. node.Body.Statements.Insert(0,
  581. CodeBuilder.CreateSuperConstructorInvocation(super));
  582. }
  583. }
  584. if (!entity.IsStatic)
  585. CheckInstanceMethodInvocationsWithinConstructor(node);
  586. }
  587. }
  588. override public void LeaveParameterDeclaration(ParameterDeclaration node)
  589. {
  590. AssertIdentifierName(node, node.Name);
  591. CheckParameterType(node.Type);
  592. }
  593. void CheckParameterType(TypeReference type)
  594. {
  595. if (type.Entity != VoidType()) return;
  596. Error(CompilerErrorFactory.InvalidParameterType(type, VoidType()));
  597. }
  598. private IType VoidType()
  599. {
  600. return TypeSystemServices.VoidType;
  601. }
  602. void CheckFieldType(TypeReference type)
  603. {
  604. if (type.Entity != VoidType()) return;
  605. Error(CompilerErrorFactory.InvalidFieldType(type, VoidType()));
  606. }
  607. bool CheckDeclarationType(TypeReference type)
  608. {
  609. if (type.Entity != VoidType()) return true;
  610. Error(CompilerErrorFactory.InvalidDeclarationType(type, VoidType()));
  611. return false;
  612. }
  613. override public void OnBlockExpression(BlockExpression node)
  614. {
  615. if (WasVisited(node)) return;
  616. if (ShouldDeferClosureProcessing(node)) return;
  617. InferClosureSignature(node);
  618. ProcessClosureBody(node);
  619. }
  620. private void InferClosureSignature(BlockExpression node)
  621. {
  622. ClosureSignatureInferrer inferrer = new ClosureSignatureInferrer(node);
  623. ICallableType inferredCallableType = inferrer.InferCallableType();
  624. BindExpressionType(node, inferredCallableType);
  625. AddInferredClosureParameterTypes(node, inferredCallableType);
  626. }
  627. private bool ShouldDeferClosureProcessing(BlockExpression node)
  628. {
  629. // Defer closure processing if it's an argument in a generic method invocation
  630. MethodInvocationExpression methodInvocationContext = node.ParentNode as MethodInvocationExpression;
  631. if (methodInvocationContext == null) return false;
  632. if (!methodInvocationContext.Arguments.Contains(node)) return false;
  633. if (methodInvocationContext.Target.Entity is Ambiguous)
  634. return ((Ambiguous) methodInvocationContext.Target.Entity).Any(GenericsServices.IsGenericMethod);
  635. IMethod target = methodInvocationContext.Target.Entity as IMethod;
  636. return (target != null && GenericsServices.IsGenericMethod(target));
  637. }
  638. private void AddInferredClosureParameterTypes(BlockExpression node, ICallableType callableType)
  639. {
  640. IParameter[] parameters = (callableType == null ? null : callableType.GetSignature().Parameters);
  641. for (int i = 0; i < node.Parameters.Count; i++)
  642. {
  643. ParameterDeclaration pd = node.Parameters[i];
  644. if (pd.Type != null) continue;
  645. IType inferredType;
  646. if (parameters != null && i < parameters.Length)
  647. {
  648. inferredType = parameters[i].Type;
  649. }
  650. else if (pd.IsParamArray)
  651. {
  652. inferredType = TypeSystemServices.ObjectArrayType;
  653. }
  654. else
  655. {
  656. inferredType = TypeSystemServices.ObjectType;
  657. }
  658. pd.Type = CodeBuilder.CreateTypeReference(inferredType);
  659. }
  660. }
  661. void ProcessClosureBody(BlockExpression node)
  662. {
  663. MarkVisited(node);
  664. if (node.ContainsAnnotation("inline"))
  665. AddOptionalReturnStatement(node.Body);
  666. var explicitClosureName = node[BlockExpression.ClosureNameAnnotation] as string;
  667. Method closure = CodeBuilder.CreateMethod(
  668. ClosureName(explicitClosureName),
  669. node.ReturnType ?? CodeBuilder.CreateTypeReference(Unknown.Default),
  670. ClosureModifiers());
  671. MarkVisited(closure);
  672. var closureEntity = (InternalMethod)closure.Entity;
  673. closure.LexicalInfo = node.LexicalInfo;
  674. closure.Parameters = node.Parameters;
  675. closure.Body = node.Body;
  676. CurrentMethod.DeclaringType.Members.Add(closure);
  677. CodeBuilder.BindParameterDeclarations(_currentMethod.IsStatic, closure);
  678. // check for invalid names and
  679. // resolve parameter types
  680. Visit(closure.Parameters);
  681. // Inside the closure, connect the closure method namespace with the current namespace
  682. var ns = new NamespaceDelegator(CurrentNamespace, closureEntity);
  683. // Allow closure body to reference itself using its explicit name (BOO-1085)
  684. if (explicitClosureName != null)
  685. ns.DelegateTo(new AliasedNamespace(explicitClosureName, closureEntity));
  686. ProcessMethodBody(closureEntity, ns);
  687. if (closureEntity.ReturnType is Unknown)
  688. TryToResolveReturnType(closureEntity);
  689. node.ExpressionType = closureEntity.Type;
  690. node.Entity = closureEntity;
  691. }
  692. protected Method CurrentMethod
  693. {
  694. get { return _currentMethod.Method; }
  695. }
  696. private void ProcessClosureInMethodInvocation(GenericParameterInferrer inferrer, BlockExpression closure, ICallableType formalType)
  697. {
  698. var sig = formalType.GetSignature();
  699. var replacer = new TypeReplacer();
  700. var collector = new TypeCollector(delegate(IType t)
  701. {
  702. IGenericParameter gp = t as IGenericParameter;
  703. if (gp == null) return false;
  704. return gp.DeclaringEntity == inferrer.GenericMethod;
  705. });
  706. collector.Visit(formalType);
  707. foreach (var typeParameter in collector.Matches)
  708. {
  709. var inferredType = inferrer.GetInferredType((IGenericParameter)typeParameter);
  710. if (inferredType != null)
  711. replacer.Replace(typeParameter, inferredType);
  712. }
  713. for (var i = 0; i < sig.Parameters.Length; i++)
  714. {
  715. var pd = closure.Parameters[i];
  716. if (pd.Type != null) continue;
  717. pd.Type = CodeBuilder.CreateTypeReference(replacer.MapType(sig.Parameters[i].Type));
  718. }
  719. ProcessClosureBody(closure);
  720. }
  721. private TypeMemberModifiers ClosureModifiers()
  722. {
  723. var modifiers = TypeMemberModifiers.Internal;
  724. if (_currentMethod.IsStatic)
  725. modifiers |= TypeMemberModifiers.Static;
  726. return modifiers;
  727. }
  728. private string ClosureName(string explicitName)
  729. {
  730. string closureHint = explicitName ?? "closure";
  731. return Context.GetUniqueName(_currentMethod.Name, closureHint);
  732. }
  733. private static void AddOptionalReturnStatement(Block body)
  734. {
  735. if (body.Statements.Count != 1) return;
  736. var stmt = body.FirstStatement as ExpressionStatement;
  737. if (null == stmt) return;
  738. var rs = new ReturnStatement(stmt.LexicalInfo, stmt.Expression, null);
  739. rs.Annotate(OptionalReturnStatementAnnotation);
  740. body.Replace(stmt, rs);
  741. }
  742. override public void OnMethod(Method method)
  743. {
  744. if (WasVisited(method)) return;
  745. MarkVisited(method);
  746. Visit(method.Attributes);
  747. Visit(method.Parameters);
  748. Visit(method.ReturnType);
  749. Visit(method.ReturnTypeAttributes);
  750. bool ispinvoke = GetEntity(method).IsPInvoke;
  751. if (method.IsRuntime || ispinvoke)
  752. {
  753. CheckRuntimeMethod(method);
  754. if (ispinvoke)
  755. {
  756. method.Modifiers |= TypeMemberModifiers.Static;
  757. }
  758. }
  759. else
  760. {
  761. try
  762. {
  763. PushMember(method);
  764. ProcessRegularMethod(method);
  765. }
  766. finally
  767. {
  768. PopMember();
  769. }
  770. }
  771. }
  772. void CheckIfIsMethodOverride(InternalMethod method)
  773. {
  774. if (method.IsStatic) return;
  775. if (method.IsNew) return;
  776. var overriden = FindMethodOverridenBy(method);
  777. if (overriden == null) return;
  778. if (CanBeOverriden(overriden))
  779. ProcessMethodOverride(method, overriden);
  780. else if (InStrictMode())
  781. CantOverrideNonVirtual(method.Method, overriden);
  782. else
  783. MethodHidesInheritedNonVirtual(method, overriden);
  784. }
  785. private bool InStrictMode()
  786. {
  787. return Parameters.Strict;
  788. }
  789. private void MethodHidesInheritedNonVirtual(InternalMethod hidingMethod, IMethod hiddenMethod)
  790. {
  791. Warnings.Add(CompilerWarningFactory.MethodHidesInheritedNonVirtual(hidingMethod.Method, hidingMethod, hiddenMethod));
  792. }
  793. IMethod FindPropertyAccessorOverridenBy(Property property, Method accessor)
  794. {
  795. var baseProperty = ((InternalProperty)property.Entity).Overriden;
  796. if (baseProperty == null)
  797. return null;
  798. var baseAccessor = property.Getter == accessor ? baseProperty.GetGetMethod() : baseProperty.GetSetMethod();
  799. if (baseAccessor != null && TypeSystemServices.CheckOverrideSignature((IMethod) accessor.Entity, baseAccessor))
  800. return baseAccessor;
  801. return null;
  802. }
  803. IMethod FindMethodOverridenBy(InternalMethod entity)
  804. {
  805. var method = entity.Method;
  806. if (method.ParentNode.NodeType == NodeType.Property)
  807. return FindPropertyAccessorOverridenBy((Property)method.ParentNode, method);
  808. var baseType = entity.DeclaringType.BaseType;
  809. var candidates = NameResolutionService.Resolve(baseType, entity.Name, EntityType.Method);
  810. if (candidates == null)
  811. return null;
  812. var baseMethod = FindMethodOverridenBy(entity, candidates);
  813. if (baseMethod != null) EnsureRelatedNodeWasVisited(method, baseMethod);
  814. return baseMethod;
  815. }
  816. private static IMethod FindMethodOverridenBy(InternalMethod entity, IEntity candidates)
  817. {
  818. if (EntityType.Method == candidates.EntityType)
  819. {
  820. var candidate = (IMethod)candidates;
  821. if (TypeSystemServices.CheckOverrideSignature(entity, candidate))
  822. return candidate;
  823. }
  824. if (candidates.IsAmbiguous())
  825. foreach (IMethod candidate in ((Ambiguous) candidates).Entities)
  826. if (TypeSystemServices.CheckOverrideSignature(entity, candidate))
  827. return candidate;
  828. return null;
  829. }
  830. void ResolveMethodOverride(InternalMethod entity)
  831. {
  832. var baseMethod = FindMethodOverridenBy(entity);
  833. if (baseMethod == null)
  834. {
  835. var suggestion = GetMostSimilarBaseMethodName(entity);
  836. if (suggestion == entity.Name) //same name => incompatible signature
  837. Error(CompilerErrorFactory.NoMethodToOverride(entity.Method, entity, true));
  838. else //suggestion (or null)
  839. Error(CompilerErrorFactory.NoMethodToOverride(entity.Method, entity, suggestion));
  840. }
  841. else
  842. ValidateOverride(entity, baseMethod);
  843. }
  844. private string GetMostSimilarBaseMethodName(InternalMethod entity)
  845. {
  846. return NameResolutionService.GetMostSimilarMemberName(entity.DeclaringType.BaseType, entity.Name, EntityType.Method);
  847. }
  848. private void ValidateOverride(InternalMethod entity, IMethod baseMethod)
  849. {
  850. if (CanBeOverriden(baseMethod))
  851. ProcessMethodOverride(entity, baseMethod);
  852. else
  853. CantOverrideNonVirtual(entity.Method, baseMethod);
  854. }
  855. private bool CanBeOverriden(IMethod baseMethod)
  856. {
  857. return baseMethod.IsVirtual && !baseMethod.IsFinal;
  858. }
  859. void ProcessMethodOverride(InternalMethod entity, IMethod baseMethod)
  860. {
  861. CallableSignature baseSignature = TypeSystemServices.GetOverriddenSignature(baseMethod, entity);
  862. if (TypeSystemServices.IsUnknown(entity.ReturnType))
  863. {
  864. entity.Method.ReturnType = CodeBuilder.CreateTypeReference(entity.Method.LexicalInfo, baseSignature.ReturnType);
  865. }
  866. else if (baseSignature.ReturnType != entity.ReturnType)
  867. {
  868. Error(CompilerErrorFactory.InvalidOverrideReturnType(
  869. entity.Method.ReturnType,
  870. baseMethod,
  871. baseMethod.ReturnType,
  872. entity.ReturnType));
  873. }
  874. SetOverride(entity, baseMethod);
  875. }
  876. void CantOverrideNonVirtual(Method method, IMethod baseMethod)
  877. {
  878. Error(CompilerErrorFactory.CantOverrideNonVirtual(method, baseMethod));
  879. }
  880. static void SetPropertyAccessorOverride(Method accessor)
  881. {
  882. if (null == accessor) return;
  883. accessor.Modifiers |= TypeMemberModifiers.Override;
  884. }
  885. IProperty ResolvePropertyOverride(IProperty p, IEntity[] candidates)
  886. {
  887. foreach (IEntity candidate in candidates)
  888. {
  889. if (EntityType.Property != candidate.EntityType) continue;
  890. IProperty candidateProperty = (IProperty)candidate;
  891. if (CheckOverrideSignature(p, candidateProperty))
  892. {
  893. return candidateProperty;
  894. }
  895. }
  896. return null;
  897. }
  898. static bool CheckOverrideSignature(IProperty p, IProperty candidate)
  899. {
  900. return TypeSystemServices.CheckOverrideSignature(p.GetParameters(), candidate.GetParameters());
  901. }
  902. void ResolvePropertyOverride(Property property)
  903. {
  904. var overriden = FindPropertyOverridenBy(property);
  905. if (overriden == null)
  906. return;
  907. EntityFor(property).Overriden = overriden;
  908. EnsureRelatedNodeWasVisited(property, overriden);
  909. PropagateOverrideToAccessors(property);
  910. if (property.Type == null)
  911. property.Type = CodeBuilder.CreateTypeReference(EntityFor(property).Overriden.Type);
  912. }
  913. private void PropagateOverrideToAccessors(Property property)
  914. {
  915. if (property.IsOverride)
  916. {
  917. SetPropertyAccessorOverride(property.Getter);
  918. SetPropertyAccessorOverride(property.Setter);
  919. return;
  920. }
  921. var overridenProperty = EntityFor(property).Overriden;
  922. if (overridenProperty.GetGetMethod() != null)
  923. SetPropertyAccessorOverride(property.Getter);
  924. if (overridenProperty.GetSetMethod() != null)
  925. SetPropertyAccessorOverride(property.Setter);
  926. }
  927. private InternalProperty EntityFor(Property property)
  928. {
  929. return ((InternalProperty) property.Entity);
  930. }
  931. private IProperty FindPropertyOverridenBy(Property property)
  932. {
  933. var baseType = EntityFor(property).DeclaringType.BaseType;
  934. var candidates = NameResolutionService.Resolve(baseType, property.Name, EntityType.Property);
  935. if (candidates != null)
  936. {
  937. if (EntityType.Property == candidates.EntityType)
  938. {
  939. var candidate = (IProperty)candidates;
  940. if (CheckOverrideSignature(EntityFor(property), candidate))
  941. return candidate;
  942. }
  943. else if (candidates.IsAmbiguous())
  944. return ResolvePropertyOverride(EntityFor(property), ((Ambiguous)candidates).Entities);
  945. }
  946. return null;
  947. }
  948. void SetOverride(InternalMethod entity, IMethod baseMethod)
  949. {
  950. TraceOverride(entity.Method, baseMethod);
  951. entity.Overriden = baseMethod;
  952. entity.Method.Modifiers |= TypeMemberModifiers.Override;
  953. }
  954. void TraceOverride(Method method, IMethod baseMethod)
  955. {
  956. _context.TraceInfo("{0}: Method '{1}' overrides '{2}'", method.LexicalInfo, method.Name, baseMethod);
  957. }
  958. sealed class ReturnExpressionFinder : FastDepthFirstVisitor
  959. {
  960. bool _hasReturnStatements;
  961. bool _hasYieldStatements;
  962. public ReturnExpressionFinder(Method node)
  963. {
  964. Visit(node.Body);
  965. }
  966. public bool HasReturnStatements
  967. {
  968. get { return _hasReturnStatements; }
  969. }
  970. public bool HasYieldStatements
  971. {
  972. get { return _hasYieldStatements; }
  973. }
  974. public override void OnReturnStatement(ReturnStatement node)
  975. {
  976. _hasReturnStatements |= (null != node.Expression);
  977. }
  978. public override void OnYieldStatement(YieldStatement node)
  979. {
  980. _hasYieldStatements = true;
  981. }
  982. }
  983. protected bool HasNeitherReturnNorYield(Method node)
  984. {
  985. var finder = new ReturnExpressionFinder(node);
  986. return !(finder.HasReturnStatements || finder.HasYieldStatements);
  987. }
  988. void PreProcessMethod(Method node)
  989. {
  990. if (WasAlreadyPreProcessed(node))
  991. return;
  992. MarkPreProcessed(node);
  993. var entity = (InternalMethod)GetEntity(node);
  994. if (node.IsOverride)
  995. ResolveMethodOverride(entity);
  996. else
  997. {
  998. CheckIfIsMethodOverride(entity);
  999. if (TypeSystemServices.IsUnknown(entity.ReturnType) && HasNeitherReturnNorYield(node))
  1000. node.ReturnType = CodeBuilder.CreateTypeReference(node.LexicalInfo, TypeSystemServices.VoidType);
  1001. }
  1002. }
  1003. static readonly object PreProcessedKey = new object();
  1004. private static bool WasAlreadyPreProcessed(Method node)
  1005. {
  1006. return node.ContainsAnnotation(PreProcessedKey);
  1007. }
  1008. private static void MarkPreProcessed(Method node)
  1009. {
  1010. node[PreProcessedKey] = PreProcessedKey;
  1011. }
  1012. void ProcessRegularMethod(Method node)
  1013. {
  1014. PreProcessMethod(node);
  1015. var entity = (InternalMethod) GetEntity(node);
  1016. ProcessMethodBody(entity);
  1017. PostProcessMethod(node);
  1018. }
  1019. private void PostProcessMethod(Method node)
  1020. {
  1021. var parentIsClass = node.DeclaringType.NodeType == NodeType.ClassDefinition;
  1022. if (!parentIsClass) return;
  1023. var entity = (InternalMethod)GetEntity(node);
  1024. if (TypeSystemServices.IsUnknown(entity.ReturnType))
  1025. TryToResolveReturnType(entity);
  1026. else
  1027. {
  1028. if (entity.IsGenerator)
  1029. {
  1030. CheckGeneratorReturnType(node, entity.ReturnType);
  1031. CheckGeneratorYieldType(entity, entity.ReturnType);
  1032. }
  1033. }
  1034. CheckGeneratorCantReturnValues(entity);
  1035. }
  1036. void CheckGeneratorCantReturnValues(InternalMethod entity)
  1037. {
  1038. if (!entity.IsGenerator) return;
  1039. if (null == entity.ReturnExpressions) return;
  1040. foreach (Expression e in entity.ReturnExpressions)
  1041. {
  1042. Error(CompilerErrorFactory.GeneratorCantReturnValue(e));
  1043. }
  1044. }
  1045. void CheckGeneratorReturnType(Method method, IType returnType)
  1046. {
  1047. bool validReturnType =
  1048. (TypeSystemServices.IEnumerableType == returnType ||
  1049. TypeSystemServices.IEnumeratorType == returnType ||
  1050. TypeSystemServices.IsSystemObject(returnType) ||
  1051. TypeSystemServices.IsGenericGeneratorReturnType(returnType));
  1052. if (!validReturnType)
  1053. {
  1054. Error(CompilerErrorFactory.InvalidGeneratorReturnType(method.ReturnType, returnType));
  1055. }
  1056. }
  1057. void CheckGeneratorYieldType(InternalMethod method, IType returnType)
  1058. {
  1059. if (!TypeSystemServices.IsGenericGeneratorReturnType(returnType))
  1060. return;
  1061. IType returnElementType = returnType.ConstructedInfo.GenericArguments[0];
  1062. foreach (var yieldExpression in method.YieldExpressions)
  1063. {
  1064. var yieldType = yieldExpression.ExpressionType;
  1065. if (!IsAssignableFrom(returnElementType, yieldType) &&
  1066. !TypeSystemServices.CanBeReachedByDownCastOrPromotion(returnElementType, yieldType))
  1067. {
  1068. Error(CompilerErrorFactory.YieldTypeDoesNotMatchReturnType(
  1069. yieldExpression, yieldType, returnElementType));
  1070. }
  1071. }
  1072. }
  1073. void ProcessMethodBody(InternalMethod entity)
  1074. {
  1075. ProcessMethodBody(entity, entity);
  1076. }
  1077. void ProcessMethodBody(InternalMethod entity, INamespace ns)
  1078. {
  1079. ProcessNodeInMethodContext(entity, ns, entity.Method.Body);
  1080. }
  1081. void ProcessNodeInMethodContext(InternalMethod entity, INamespace ns, Node node)
  1082. {
  1083. PushMethodInfo(entity);
  1084. EnterNamespace(ns);
  1085. try
  1086. {
  1087. Visit(node);
  1088. }
  1089. finally
  1090. {
  1091. LeaveNamespace();
  1092. PopMethodInfo();
  1093. }
  1094. }
  1095. void ResolveGeneratorReturnType(InternalMethod entity)
  1096. {
  1097. IType returnType = GetGeneratorReturnType(entity);
  1098. entity.Method.ReturnType = CodeBuilder.CreateTypeReference(returnType);
  1099. }
  1100. /// <summary>
  1101. /// Allows a different language to use custom rules for generator
  1102. /// return types.
  1103. /// </summary>
  1104. /// <param name="generator"></param>
  1105. /// <returns></returns>
  1106. protected virtual IType GetGeneratorReturnType(InternalMethod generator)
  1107. {
  1108. // Make method return a generic IEnumerable
  1109. return GeneratorTypeOf(GeneratorItemTypeFor(generator));
  1110. }
  1111. private IType GeneratorItemTypeFor(InternalMethod generator)
  1112. {
  1113. return My<GeneratorItemTypeInferrer>.Instance.GeneratorItemTypeFor(generator);
  1114. }
  1115. void TryToResolveReturnType(InternalMethod entity)
  1116. {
  1117. if (entity.IsGenerator)
  1118. {
  1119. ResolveGeneratorReturnType(entity);
  1120. return;
  1121. }
  1122. if (CanResolveReturnType(entity))
  1123. ResolveReturnType(entity);
  1124. }
  1125. override public void OnSuperLiteralExpression(SuperLiteralExpression node)
  1126. {
  1127. if (!AstUtil.IsTargetOfMethodInvocation(node))
  1128. {
  1129. node.ExpressionType = _currentMethod.DeclaringType.BaseType;
  1130. return;
  1131. }
  1132. if (EntityType.Constructor == _currentMethod.EntityType)
  1133. {
  1134. // TODO: point to super ctor
  1135. node.Entity = _currentMethod;
  1136. return;
  1137. }
  1138. if (null == _currentMethod.Overriden)
  1139. {
  1140. Error(node,
  1141. CompilerErrorFactory.MethodIsNotOverride(node, _currentMethod));
  1142. return;
  1143. }
  1144. node.Entity = _currentMethod.Overriden;
  1145. }
  1146. static bool CanResolveReturnType(InternalMethod method)
  1147. {
  1148. var expressions = method.ReturnExpressions;
  1149. if (null != expressions)
  1150. {
  1151. foreach (var expression in expressions)
  1152. {
  1153. IType type = expression.ExpressionType;
  1154. if (type == null || TypeSystemServices.IsUnknown(type))
  1155. return false;
  1156. }
  1157. }
  1158. return true;
  1159. }
  1160. void ResolveReturnType(InternalMethod entity)
  1161. {
  1162. var method = entity.Method;
  1163. method.ReturnType = entity.ReturnExpressions == null
  1164. ? CodeBuilder.CreateTypeReference(TypeSystemServices.VoidType)
  1165. : GetMostGenericTypeReference(entity.ReturnExpressions);
  1166. TraceReturnType(method, entity);
  1167. }
  1168. private TypeReference GetMostGenericTypeReference(ExpressionCollection expressions)
  1169. {
  1170. var type = MapWildcardType(GetMostGenericType(expressions));
  1171. return CodeBuilder.CreateTypeReference(type);
  1172. }
  1173. IType MapWildcardType(IType type)
  1174. {
  1175. return TypeSystemServices.MapWildcardType(type);
  1176. }
  1177. IType GetMostGenericType(IType lhs, IType rhs)
  1178. {
  1179. return TypeSystemServices.GetMostGenericType(lhs, rhs);
  1180. }
  1181. IType GetMostGenericType(ExpressionCollection args)
  1182. {
  1183. return TypeSystemServices.GetMostGenericType(args);
  1184. }
  1185. override public void OnBoolLiteralExpression(BoolLiteralExpression node)
  1186. {
  1187. BindExpressionType(node, TypeSystemServices.BoolType);
  1188. }
  1189. override public void OnTimeSpanLiteralExpression(TimeSpanLiteralExpression node)
  1190. {
  1191. BindExpressionType(node, TypeSystemServices.TimeSpanType);
  1192. }
  1193. override public void OnIntegerLiteralExpression(IntegerLiteralExpression node)
  1194. {
  1195. BindExpressionType(node, node.IsLong ? TypeSystemServices.LongType : TypeSystemServices.IntType);
  1196. }
  1197. override public void OnDoubleLiteralExpression(DoubleLiteralExpression node)
  1198. {
  1199. BindExpressionType(node, node.IsSingle ? TypeSystemServices.SingleType : TypeSystemServices.DoubleType);
  1200. }
  1201. override public void OnStringLiteralExpression(StringLiteralExpression node)
  1202. {
  1203. BindExpressionType(node, TypeSystemServices.StringType);
  1204. }
  1205. override public void OnCharLiteralExpression(CharLiteralExpression node)
  1206. {
  1207. CheckCharLiteralValue(node);
  1208. BindExpressionType(node, TypeSystemServices.CharType);
  1209. }
  1210. private void CheckCharLiteralValue(CharLiteralExpression node)
  1211. {
  1212. var value = node.Value;
  1213. if (value == null || value.Length != 1)
  1214. Errors.Add(CompilerErrorFactory.InvalidCharLiteral(node, value));
  1215. }
  1216. static IEntity[] GetSetMethods(IEntity[] entities)
  1217. {
  1218. return GetPropertyAccessors(entities, p => p.GetSetMethod());
  1219. }
  1220. private static IEntity[] GetGetMethods(IEntity[] entities)
  1221. {
  1222. return GetPropertyAccessors(entities, p => p.GetGetMethod());
  1223. }
  1224. private static IEntity[] GetPropertyAccessors(IEntity[] entities, Func<IProperty, IEntity> selector)
  1225. {
  1226. return entities.OfType<IProperty>().Select(selector).Distinct().ToArray();
  1227. }
  1228. void AssertIsNotComplexSlicing(SlicingExpression node)
  1229. {
  1230. if (node.IsComplexSlicing())
  1231. NotImplemented(node, "complex slicing");
  1232. }
  1233. protected MethodInvocationExpression CreateEquals(BinaryExpression node)
  1234. {
  1235. return CodeBuilder.CreateMethodInvocation(MethodCache.RuntimeServices_EqualityOperator, node.Left, node.Right);
  1236. }
  1237. protected bool IsIndexedProperty(Expression expression)
  1238. {
  1239. return expression.Entity.IsIndexedProperty();
  1240. }
  1241. override public void LeaveSlicingExpression(SlicingExpression node)
  1242. {
  1243. if (node.Target.Entity.IsAmbiguous())
  1244. {
  1245. BindIndexedPropertySlicing(node);
  1246. return;
  1247. }
  1248. // target[indices]
  1249. var targetType = GetExpressionType(node.Target);
  1250. if (IsError(targetType))
  1251. {
  1252. Error(node);
  1253. return;
  1254. }
  1255. if (node.IsComplexSlicing())
  1256. {
  1257. BindExpressionType(node, ResultingTypeForComplexSlicing(node));
  1258. return;
  1259. }
  1260. if (IsIndexedProperty(node.Target))
  1261. {
  1262. BindIndexedPropertySlicing(node);
  1263. return;
  1264. }
  1265. if (targetType.IsArray)
  1266. {
  1267. BindExpressionType(node, targetType.ElementType);
  1268. return;
  1269. }
  1270. var member = TypeSystemServices.GetDefaultMember(targetType);
  1271. if (member == null)
  1272. {
  1273. Error(node, CompilerErrorFactory.TypeDoesNotSupportSlicing(node.Target, targetType));
  1274. return;
  1275. }
  1276. node.Target = new MemberReferenceExpression(node.LexicalInfo, node.Target, member.Name)
  1277. {
  1278. Entity = member,
  1279. ExpressionType = Null.Default // to be resolved later
  1280. };
  1281. SliceMember(node, member);
  1282. }
  1283. private IType ResultingTypeForComplexSlicing(SlicingExpression node)
  1284. {
  1285. var targetType = GetExpressionType(node.Target);
  1286. return targetType.IsArray ? ResultingTypeForArraySlicing(node) : targetType;
  1287. }
  1288. IType ResultingTypeForArraySlicing(SlicingExpression node)
  1289. {
  1290. var arrayType = GetExpressionType(node.Target);
  1291. if (node.Indices.Count > 1)
  1292. {
  1293. var collapseCount = node.Indices.Count(t => t.End == null);
  1294. return arrayType.ElementType.MakeArrayType(node.Indices.Count - collapseCount);
  1295. }
  1296. return arrayType;
  1297. }
  1298. private void BindIndexedPropertySlicing(SlicingExpression node)
  1299. {
  1300. AssertIsNotComplexSlicing(node);
  1301. SliceMember(node, node.Target.Entity);
  1302. }
  1303. void SliceMember(SlicingExpression node, IEntity member)
  1304. {
  1305. EnsureRelatedNodeWasVisited(node, member);
  1306. if (node.IsTargetOfAssignment())
  1307. {
  1308. // leave it to LeaveBinaryExpression to resolve
  1309. Bind(node, member);
  1310. return;
  1311. }
  1312. MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo);
  1313. foreach (Slice index in node.Indices)
  1314. {
  1315. mie.Arguments.Add(index.Begin);
  1316. }
  1317. IMethod getter = null;
  1318. if (member.IsAmbiguous())
  1319. {
  1320. IEntity result = ResolveAmbiguousPropertyReference((ReferenceExpression)node.Target, (Ambiguous)member, mie.Arguments);
  1321. IProperty found = result as IProperty;
  1322. if (null != found)
  1323. {
  1324. getter = found.GetGetMethod();
  1325. }
  1326. else if (result.IsAmbiguous())
  1327. {
  1328. Error(node);
  1329. return;
  1330. }
  1331. }
  1332. else if (EntityType.Property == member.EntityType)
  1333. {
  1334. getter = ((IProperty)member).GetGetMethod();
  1335. }
  1336. if (null != getter)
  1337. {
  1338. if (AssertParameters(node, getter, mie.Arguments))
  1339. {
  1340. Expression target = GetIndexedPropertySlicingTarget(node);
  1341. mie.Target = CodeBuilder.CreateMemberReference(target, getter);
  1342. BindExpressionType(mie, getter.ReturnType);
  1343. node.ParentNode.Replace(node, mie);
  1344. }
  1345. else
  1346. {
  1347. Error(node);
  1348. }
  1349. }
  1350. else
  1351. {
  1352. NotImplemented(node, "slice for anything but arrays and default properties");
  1353. }
  1354. }
  1355. private Expression GetIndexedPropertySlicingTarget(SlicingExpression node)
  1356. {
  1357. Expression target = node.Target;
  1358. MemberReferenceExpression mre = target as MemberReferenceExpression;
  1359. if (null != mre) return mre.Target;
  1360. return CreateSelfReference();
  1361. }
  1362. override public void LeaveExpressionInterpolationExpression(ExpressionInterpolationExpression node)
  1363. {
  1364. BindExpressionType(node, TypeSystemServices.StringType);
  1365. }
  1366. override public void LeaveListLiteralExpression(ListLiteralExpression node)
  1367. {
  1368. BindExpressionType(node, TypeSystemServices.ListType);
  1369. TypeSystemServices.MapToConcreteExpressionTypes(node.Items);
  1370. }
  1371. override public void OnExtendedGeneratorExpression(ExtendedGeneratorExpression node)
  1372. {
  1373. BlockExpression block = new BlockExpression(node.LexicalInfo);
  1374. Block body = block.Body;
  1375. Expression e = node.Items[0].Expression;
  1376. foreach (GeneratorExpression ge in node.Items)
  1377. {
  1378. ForStatement fs = new ForStatement(ge.LexicalInfo);
  1379. fs.Iterator = ge.Iterator;
  1380. fs.Declarations = ge.Declarations;
  1381. body.Add(fs);
  1382. if (null == ge.Filter)
  1383. {
  1384. body = fs.Block;
  1385. }
  1386. else
  1387. {
  1388. fs.Block.Add(
  1389. NormalizeStatementModifiers.MapStatementModifier(ge.Filter, out body));
  1390. }
  1391. }
  1392. body.Add(new YieldStatement(e.LexicalInfo, e));
  1393. MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo);
  1394. mie.Target = block;
  1395. Node parentNode = node.ParentNode;
  1396. bool isGenerator = AstUtil.IsListMultiGenerator(parentNode);
  1397. parentNode.Replace(node, mie);
  1398. mie.Accept(this);
  1399. if (isGenerator)
  1400. {
  1401. parentNode.ParentNode.Replace(
  1402. parentNode,
  1403. CodeBuilder.CreateConstructorInvocation(
  1404. TypeSystemServices.Map(ProcessGenerators.List_IEnumerableConstructor),
  1405. mie));
  1406. }
  1407. }
  1408. override public void OnGeneratorExpression(GeneratorExpression node)
  1409. {
  1410. Visit(node.Iterator);
  1411. node.Iterator = ProcessIterator(node.Iterator, node.Declarations);
  1412. EnterNamespace(new DeclarationsNamespace(CurrentNamespace, node.Declarations));
  1413. Visit(node.Filter);
  1414. Visit(node.Expression);
  1415. LeaveNamespace();
  1416. IType generatorItemType = TypeSystemServices.GetConcreteExpressionType(node.Expression);
  1417. BindExpressionType(node, GeneratorTypeOf(generatorItemType));
  1418. }
  1419. private IType GeneratorTypeOf(IType generatorItemType)
  1420. {
  1421. if (generatorItemType == TypeSystemServices.VoidType)
  1422. // cannot use 'void' as a generic argument
  1423. return TypeSystemServices.ErrorEntity;
  1424. return GetConstructedType(TypeSystemServices.IEnumerableGenericType, generatorItemType);
  1425. }
  1426. protected IType GetConstructedType(IType genericType, IType argType)
  1427. {
  1428. return genericType.GenericInfo.ConstructType(argType);
  1429. }
  1430. override public void LeaveHashLiteralExpression(HashLiteralExpression node)
  1431. {
  1432. BindExpressionType(node, TypeSystemServices.HashType);
  1433. foreach (ExpressionPair pair in node.Items)
  1434. {
  1435. GetConcreteExpressionType(pair.First);
  1436. GetConcreteExpressionType(pair.Second);
  1437. }
  1438. }
  1439. override public void LeaveArrayLiteralExpression(ArrayLiteralExpression node)
  1440. {
  1441. TypeSystemServices.MapToConcreteExpressionTypes(node.Items);
  1442. var type = InferArrayType(node);
  1443. BindExpressionType(node, type);
  1444. if (node.Type == null)
  1445. node.Type = (ArrayTypeReference)CodeBuilder.CreateTypeReference(type);
  1446. else
  1447. CheckItems(type.ElementType, node.Items);
  1448. }
  1449. private IArrayType InferArrayType(ArrayLiteralExpression node)
  1450. {
  1451. if (null != node.Type) return (IArrayType)node.Type.Entity;
  1452. if (node.Items.Count == 0) return EmptyArrayType.Default;
  1453. return GetMostGenericType(node.Items).MakeArrayType(1);
  1454. }
  1455. override public void LeaveDeclaratio

Large files files are truncated, but you can click here to view the full file