PageRenderTime 36ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 2ms

/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
  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 LeaveDeclaration(Declaration node)
  1456. {
  1457. if (null == node.Type) return;
  1458. CheckDeclarationType(node.Type);
  1459. }
  1460. override public void LeaveDeclarationStatement(DeclarationStatement node)
  1461. {
  1462. EnsureDeclarationType(node);
  1463. AssertDeclarationName(node.Declaration);
  1464. var type = GetDeclarationType(node);
  1465. var localInfo = DeclareLocal(node, node.Declaration.Name, type);
  1466. var loopLocal = localInfo as InternalLocal;
  1467. if (null != loopLocal)
  1468. loopLocal.OriginalDeclaration = node.Declaration;
  1469. if (node.Initializer != null)
  1470. {
  1471. IType initializerType = GetExpressionType(node.Initializer);
  1472. if (CheckDeclarationType(node.Declaration.Type))
  1473. AssertTypeCompatibility(node.Initializer, type, initializerType);
  1474. if (TypeSystemServices.IsNullable(type) && !TypeSystemServices.IsNullable(initializerType))
  1475. BindNullableInitializer(node, node.Initializer, type);
  1476. node.ReplaceBy(
  1477. new ExpressionStatement(
  1478. CodeBuilder.CreateAssignment(
  1479. node.LexicalInfo,
  1480. CodeBuilder.CreateReference(localInfo),
  1481. node.Initializer)));
  1482. }
  1483. else
  1484. node.ReplaceBy(new ExpressionStatement(CreateDefaultLocalInitializer(node, localInfo)));
  1485. }
  1486. private IType GetDeclarationType(DeclarationStatement node)
  1487. {
  1488. return GetType(node.Declaration.Type);
  1489. }
  1490. private void EnsureDeclarationType(DeclarationStatement node)
  1491. {
  1492. var declaration = node.Declaration;
  1493. if (declaration.Type != null) return;
  1494. declaration.Type = CodeBuilder.CreateTypeReference(declaration.LexicalInfo, InferDeclarationType(node));
  1495. }
  1496. private IType InferDeclarationType(DeclarationStatement node)
  1497. {
  1498. if (null == node.Initializer) return TypeSystemServices.ObjectType;
  1499. // The boo syntax does not require this check because
  1500. // there's no way to create an untyped declaration statement.
  1501. // This is here to support languages that do allow untyped variable
  1502. // declarations (unityscript is such an example).
  1503. return MapWildcardType(GetConcreteExpressionType(node.Initializer));
  1504. }
  1505. virtual protected Expression CreateDefaultLocalInitializer(Node sourceNode, IEntity local)
  1506. {
  1507. return CodeBuilder.CreateDefaultInitializer(
  1508. sourceNode.LexicalInfo,
  1509. (InternalLocal)local);
  1510. }
  1511. override public void LeaveExpressionStatement(ExpressionStatement node)
  1512. {
  1513. AssertHasSideEffect(node.Expression);
  1514. }
  1515. override public void OnNullLiteralExpression(NullLiteralExpression node)
  1516. {
  1517. BindExpressionType(node, Null.Default);
  1518. }
  1519. override public void OnSelfLiteralExpression(SelfLiteralExpression node)
  1520. {
  1521. if (null == _currentMethod)
  1522. {
  1523. Error(node, CompilerErrorFactory.SelfOutsideMethod(node));
  1524. return;
  1525. }
  1526. if (_currentMethod.IsStatic)
  1527. {
  1528. if (NodeType.MemberReferenceExpression != node.ParentNode.NodeType)
  1529. {
  1530. // if we are inside a MemberReferenceExpression
  1531. // let the MemberReferenceExpression deal with it
  1532. // as it can provide a better message
  1533. Error(CompilerErrorFactory.SelfIsNotValidInStaticMember(node));
  1534. }
  1535. }
  1536. node.Entity = _currentMethod;
  1537. node.ExpressionType = _currentMethod.DeclaringType;
  1538. }
  1539. override public void LeaveTypeofExpression(TypeofExpression node)
  1540. {
  1541. BindExpressionType(node, TypeSystemServices.TypeType);
  1542. }
  1543. override public void LeaveCastExpression(CastExpression node)
  1544. {
  1545. var fromType = GetExpressionType(node.Target);
  1546. var toType = GetType(node.Type);
  1547. BindExpressionType(node, toType);
  1548. if (IsError(fromType) || IsError(toType))
  1549. return;
  1550. if (IsAssignableFrom(toType, fromType))
  1551. return;
  1552. if (TypeSystemServices.CanBeReachedByPromotion(toType, fromType))
  1553. return;
  1554. if (TypeSystemServices.IsFloatingPointNumber(toType) && fromType.IsEnum)
  1555. return;
  1556. var conversion = TypeSystemServices.FindExplicitConversionOperator(fromType, toType) ?? TypeSystemServices.FindImplicitConversionOperator(fromType, toType);
  1557. if (null != conversion)
  1558. {
  1559. node.ParentNode.Replace(node, CodeBuilder.CreateMethodInvocation(conversion, node.Target));
  1560. return;
  1561. }
  1562. if (toType.IsValueType)
  1563. {
  1564. if (TypeSystemServices.IsSystemObject(fromType))
  1565. return;
  1566. }
  1567. else if (!fromType.IsFinal)
  1568. return;
  1569. Error(CompilerErrorFactory.IncompatibleExpressionType(node, toType, fromType));
  1570. }
  1571. override public void LeaveTryCastExpression(TryCastExpression node)
  1572. {
  1573. var target = GetExpressionType(node.Target);
  1574. var toType = GetType(node.Type);
  1575. if (target.IsValueType)
  1576. Error(CompilerErrorFactory.CantCastToValueType(node.Target, target));
  1577. else if (toType.IsValueType)
  1578. Error(CompilerErrorFactory.CantCastToValueType(node.Type, toType));
  1579. BindExpressionType(node, toType);
  1580. }
  1581. protected Expression CreateMemberReferenceTarget(Node sourceNode, IMember member)
  1582. {
  1583. Expression target = null;
  1584. if (member.IsStatic)
  1585. {
  1586. target = CodeBuilder.CreateReference(sourceNode.LexicalInfo, member.DeclaringType);
  1587. }
  1588. else
  1589. {
  1590. //check if found entity can't possibly be a member of self:
  1591. if (member.DeclaringType != CurrentType
  1592. && !(CurrentType.IsSubclassOf(member.DeclaringType)))
  1593. {
  1594. Error(CompilerErrorFactory.InstanceRequired(sourceNode, member));
  1595. }
  1596. target = new SelfLiteralExpression(sourceNode.LexicalInfo);
  1597. }
  1598. BindExpressionType(target, member.DeclaringType);
  1599. return target;
  1600. }
  1601. protected MemberReferenceExpression MemberReferenceFromReference(ReferenceExpression node, IMember member)
  1602. {
  1603. MemberReferenceExpression memberRef = new MemberReferenceExpression(node.LexicalInfo);
  1604. memberRef.Name = node.Name;
  1605. memberRef.Target = CreateMemberReferenceTarget(node, member);
  1606. return memberRef;
  1607. }
  1608. void ResolveMemberInfo(ReferenceExpression node, IMember member)
  1609. {
  1610. MemberReferenceExpression memberRef = MemberReferenceFromReference(node, member);
  1611. Bind(memberRef, member);
  1612. node.ParentNode.Replace(node, memberRef);
  1613. Visit(memberRef);
  1614. }
  1615. override public void OnRELiteralExpression(RELiteralExpression node)
  1616. {
  1617. if (null != node.Entity)
  1618. return;
  1619. IType type = TypeSystemServices.RegexType;
  1620. BindExpressionType(node, type);
  1621. }
  1622. override public void LeaveGenericReferenceExpression(GenericReferenceExpression node)
  1623. {
  1624. if (node.Target.Entity == null || IsError(node.Target.Entity))
  1625. {
  1626. BindExpressionType(node, TypeSystemServices.ErrorEntity);
  1627. return;
  1628. }
  1629. IEntity entity = NameResolutionService.ResolveGenericReferenceExpression(node, node.Target.Entity);
  1630. Bind(node, entity);
  1631. if (entity.EntityType == EntityType.Type)
  1632. {
  1633. BindTypeReferenceExpressionType(node, (IType)entity);
  1634. return;
  1635. }
  1636. if (entity.EntityType == EntityType.Method)
  1637. BindExpressionType(node, ((IMethod)entity).Type);
  1638. if (!(node.Target is MemberReferenceExpression)) //no self.
  1639. node.Target = CodeBuilder.MemberReferenceForEntity(CreateSelfReference(), entity);
  1640. }
  1641. override public void OnReferenceExpression(ReferenceExpression node)
  1642. {
  1643. if (AlreadyBound(node))
  1644. return;
  1645. IEntity entity = ResolveName(node, node.Name);
  1646. if (null == entity)
  1647. {
  1648. Error(node);
  1649. return;
  1650. }
  1651. // BOO-314 - if we are trying to invoke
  1652. // something, let's make sure it is
  1653. // something callable, otherwise, let's
  1654. // try to find something callable
  1655. if (AstUtil.IsTargetOfMethodInvocation(node)
  1656. && !IsCallableEntity(entity))
  1657. {
  1658. IEntity callable = ResolveCallable(node);
  1659. if (null != callable) entity = callable;
  1660. }
  1661. IMember member = entity as IMember;
  1662. if (null != member)
  1663. {
  1664. if (IsExtensionMethod(member))
  1665. {
  1666. Bind(node, member);
  1667. return;
  1668. }
  1669. ResolveMemberInfo(node, member);
  1670. return;
  1671. }
  1672. EnsureRelatedNodeWasVisited(node, entity);
  1673. node.Entity = entity;
  1674. PostProcessReferenceExpression(node);
  1675. }
  1676. private static bool AlreadyBound(ReferenceExpression node)
  1677. {
  1678. return null != node.ExpressionType;
  1679. }
  1680. private IEntity ResolveCallable(ReferenceExpression node)
  1681. {
  1682. const EntityType callableEntityFlags = EntityType.Type | EntityType.Method | EntityType.BuiltinFunction | EntityType.Event;
  1683. return NameResolutionService.Resolve(node.Name, callableEntityFlags);
  1684. }
  1685. private bool IsCallableEntity(IEntity entity)
  1686. {
  1687. switch (entity.EntityType)
  1688. {
  1689. case EntityType.Method:
  1690. case EntityType.Type:
  1691. case EntityType.Event:
  1692. case EntityType.BuiltinFunction:
  1693. case EntityType.Constructor:
  1694. return true;
  1695. case EntityType.Ambiguous:
  1696. // let overload resolution deal with it
  1697. return true;
  1698. }
  1699. ITypedEntity typed = entity as ITypedEntity;
  1700. return null == typed ? false : TypeSystemServices.IsCallable(typed.Type);
  1701. }
  1702. void PostProcessReferenceExpression(ReferenceExpression node)
  1703. {
  1704. var entity = GetEntity(node);
  1705. switch (entity.EntityType)
  1706. {
  1707. case EntityType.Type:
  1708. {
  1709. BindNonGenericTypeReferenceExpressionType(node, (IType)entity);
  1710. break;
  1711. }
  1712. case EntityType.Method:
  1713. {
  1714. var method = entity as IMethod;
  1715. if (null != method && IsGenericMethod(method) && IsStandaloneReference(node) && !IsSubjectToGenericArgumentInference(node))
  1716. CannotInferGenericMethodArguments(node, method);
  1717. break;
  1718. }
  1719. case EntityType.Ambiguous:
  1720. {
  1721. var ambiguous = (Ambiguous) entity;
  1722. var resolvedEntity = ResolveAmbiguousReference(node, ambiguous);
  1723. var resolvedMember = resolvedEntity as IMember;
  1724. if (null != resolvedMember)
  1725. {
  1726. ResolveMemberInfo(node, resolvedMember);
  1727. break;
  1728. }
  1729. if (resolvedEntity is IType)
  1730. {
  1731. BindNonGenericTypeReferenceExpressionType(node, (IType)resolvedEntity);
  1732. break;
  1733. }
  1734. if (!AstUtil.IsTargetOfMethodInvocation(node)
  1735. && !AstUtil.IsTargetOfSlicing(node)
  1736. && !node.IsTargetOfAssignment())
  1737. {
  1738. Error(node, CompilerErrorFactory.AmbiguousReference(
  1739. node,
  1740. node.Name,
  1741. ambiguous.Entities));
  1742. }
  1743. break;
  1744. }
  1745. case EntityType.Namespace:
  1746. {
  1747. if (IsStandaloneReference(node))
  1748. Error(node, CompilerErrorFactory.NamespaceIsNotAnExpression(node, entity.Name));
  1749. break;
  1750. }
  1751. case EntityType.Parameter:
  1752. case EntityType.Local:
  1753. {
  1754. var local = (ILocalEntity)node.Entity;
  1755. local.IsUsed = true;
  1756. BindExpressionType(node, local.Type);
  1757. break;
  1758. }
  1759. default:
  1760. {
  1761. if (EntityType.BuiltinFunction == entity.EntityType)
  1762. {
  1763. CheckBuiltinUsage(node, entity);
  1764. }
  1765. else
  1766. {
  1767. if (node.ExpressionType == null)
  1768. {
  1769. BindExpressionType(node, ((ITypedEntity)entity).Type);
  1770. }
  1771. }
  1772. break;
  1773. }
  1774. }
  1775. }
  1776. private static bool IsGenericMethod(IMethod m)
  1777. {
  1778. return m.GenericInfo != null;
  1779. }
  1780. protected virtual void BindTypeReferenceExpressionType(Expression node, IType type)
  1781. {
  1782. if (IsStandaloneReference(node))
  1783. BindExpressionType(node, TypeSystemServices.TypeType);
  1784. else
  1785. BindExpressionType(node, type);
  1786. }
  1787. protected virtual void BindNonGenericTypeReferenceExpressionType(Expression node, IType type)
  1788. {
  1789. if (type.GenericInfo != null && !IsSubjectToGenericArgumentInference(node))
  1790. {
  1791. My<CompilerErrorEmitter>.Instance.GenericArgumentsCountMismatch(node, type);
  1792. Error(node);
  1793. return;
  1794. }
  1795. BindTypeReferenceExpressionType(node, type);
  1796. }
  1797. private bool IsSubjectToGenericArgumentInference(Expression node)
  1798. {
  1799. return (AstUtil.IsTargetOfGenericReferenceExpression(node)
  1800. || AstUtil.IsTargetOfMethodInvocation(node));
  1801. }
  1802. protected virtual void CheckBuiltinUsage(ReferenceExpression node, IEntity entity)
  1803. {
  1804. if (!AstUtil.IsTargetOfMethodInvocation(node))
  1805. {
  1806. Error(node, CompilerErrorFactory.BuiltinCannotBeUsedAsExpression(node, entity.Name));
  1807. }
  1808. }
  1809. override public bool EnterMemberReferenceExpression(MemberReferenceExpression node)
  1810. {
  1811. return null == node.ExpressionType;
  1812. }
  1813. INamespace GetReferenceNamespace(MemberReferenceExpression expression)
  1814. {
  1815. Expression target = expression.Target;
  1816. INamespace ns = target.ExpressionType;
  1817. if (null != ns)
  1818. {
  1819. return GetConcreteExpressionType(target);
  1820. }
  1821. return (INamespace)GetEntity(target);
  1822. }
  1823. protected virtual void LeaveExplodeExpression(UnaryExpression node)
  1824. {
  1825. IType type = GetConcreteExpressionType(node.Operand);
  1826. if (!type.IsArray)
  1827. Error(node, CompilerErrorFactory.ExplodedExpressionMustBeArray(node));
  1828. else
  1829. BindExpressionType(node, type);
  1830. }
  1831. override public void LeaveMemberReferenceExpression(MemberReferenceExpression node)
  1832. {
  1833. _context.TraceVerbose("LeaveMemberReferenceExpression: {0}", node);
  1834. if (TypeSystemServices.IsError(node.Target))
  1835. Error(node);
  1836. else
  1837. ProcessMemberReferenceExpression(node);
  1838. }
  1839. virtual protected void MemberNotFound(MemberReferenceExpression node, INamespace ns)
  1840. {
  1841. EntityType et = (!AstUtil.IsTargetOfMethodInvocation(node)) ? EntityType.Any : EntityType.Method;
  1842. Error(node,
  1843. CompilerErrorFactory.MemberNotFound(node, ns, NameResolutionService.GetMostSimilarMemberName(ns, node.Name, et)));
  1844. }
  1845. virtual protected bool ShouldRebindMember(IEntity entity)
  1846. {
  1847. return entity == null;
  1848. }
  1849. IEntity ResolveMember(MemberReferenceExpression node)
  1850. {
  1851. var entity = node.Entity;
  1852. if (!ShouldRebindMember(entity))
  1853. return entity;
  1854. var ns = GetReferenceNamespace(node);
  1855. var member = NameResolutionService.Resolve(ns, node.Name);
  1856. if (null == member || !IsAccessible(member) || !IsApplicable(member, node))
  1857. {
  1858. var extension = TryToResolveMemberAsExtension(node);
  1859. if (null != extension)
  1860. return extension;
  1861. }
  1862. if (null != member)
  1863. return Disambiguate(node, member);
  1864. MemberNotFound(node, ns);
  1865. return null;
  1866. }
  1867. private bool IsApplicable(IEntity entity, MemberReferenceExpression node)
  1868. {
  1869. //ProcessLenInvocation - Visit(resultingNode), call for node without parent
  1870. if (node == null || node.ParentNode == null)
  1871. return true;
  1872. if (AstUtil.IsTargetOfMethodInvocation(node)
  1873. && !IsCallableEntity(entity))
  1874. return false;
  1875. return true;
  1876. }
  1877. private IEntity Disambiguate(ReferenceExpression node, IEntity member)
  1878. {
  1879. var ambiguous = member as Ambiguous;
  1880. if (ambiguous != null)
  1881. return ResolveAmbiguousReference(node, ambiguous);
  1882. return member;
  1883. }
  1884. private IEntity TryToResolveMemberAsExtension(MemberReferenceExpression node)
  1885. {
  1886. IEntity extension = NameResolutionService.ResolveExtension(GetReferenceNamespace(node), node.Name);
  1887. if (null != extension)
  1888. node.Annotate(ResolvedAsExtensionAnnotation);
  1889. return extension;
  1890. }
  1891. virtual protected void ProcessMemberReferenceExpression(MemberReferenceExpression node)
  1892. {
  1893. var entity = ResolveMember(node);
  1894. if (null == entity)
  1895. return;
  1896. EnsureRelatedNodeWasVisited(node, entity);
  1897. if (EntityType.Namespace == entity.EntityType)
  1898. MarkRelatedImportAsUsed(node);
  1899. var member = entity as IMember;
  1900. if (member != null)
  1901. {
  1902. if (!AssertTargetContext(node, member))
  1903. {
  1904. Error(node);
  1905. return;
  1906. }
  1907. if (EntityType.Method != member.EntityType)
  1908. BindExpressionType(node, GetInferredType(member));
  1909. else
  1910. BindExpressionType(node, member.Type);
  1911. }
  1912. // TODO: check for generic methods with no generic args here
  1913. if (EntityType.Property == entity.EntityType)
  1914. {
  1915. IProperty property = (IProperty)entity;
  1916. if (property.IsIndexedProperty())
  1917. {
  1918. if (!AstUtil.IsTargetOfSlicing(node)
  1919. && (!property.IsExtension || property.GetParameters().Length > 1))
  1920. {
  1921. Error(node, CompilerErrorFactory.PropertyRequiresParameters(MemberAnchorFor(node), entity));
  1922. return;
  1923. }
  1924. }
  1925. if (IsWriteOnlyProperty(property) && !IsBeingAssignedTo(node))
  1926. {
  1927. Error(node, CompilerErrorFactory.PropertyIsWriteOnly(MemberAnchorFor(node), entity));
  1928. }
  1929. }
  1930. else if (EntityType.Event == entity.EntityType)
  1931. {
  1932. if (!AstUtil.IsTargetOfMethodInvocation(node) &&
  1933. !AstUtil.IsLhsOfInPlaceAddSubtract(node))
  1934. {
  1935. if (CurrentType == member.DeclaringType)
  1936. {
  1937. InternalEvent ev = (InternalEvent)entity;
  1938. node.Name = ev.BackingField.Name;
  1939. node.Entity = ev.BackingField;
  1940. BindExpressionType(node, ev.BackingField.Type);
  1941. return;
  1942. }
  1943. else if (!node.IsTargetOfAssignment()
  1944. || !IsNull(((BinaryExpression)node.ParentNode).Right))
  1945. {
  1946. Error(node, CompilerErrorFactory.EventIsNotAnExpression(node, entity));
  1947. }
  1948. else //event=null
  1949. {
  1950. EnsureInternalEventInvocation((IEvent) entity, node);
  1951. }
  1952. }
  1953. }
  1954. Bind(node, entity);
  1955. PostProcessReferenceExpression(node);
  1956. }
  1957. private static Node MemberAnchorFor(Node node)
  1958. {
  1959. return AstUtil.GetMemberAnchor(node);
  1960. }
  1961. private void MarkRelatedImportAsUsed(MemberReferenceExpression node)
  1962. {
  1963. string ns = null;
  1964. foreach (var import in _currentModule.Imports)
  1965. {
  1966. if (ImportAnnotations.IsUsedImport(import)) continue;
  1967. if (null == ns) ns = node.ToCodeString();
  1968. if (import.Namespace == ns)
  1969. {
  1970. ImportAnnotations.MarkAsUsed(import);
  1971. break;
  1972. }
  1973. }
  1974. }
  1975. private bool IsBeingAssignedTo(MemberReferenceExpression node)
  1976. {
  1977. Node current = node;
  1978. Node parent = current.ParentNode;
  1979. BinaryExpression be = parent as BinaryExpression;
  1980. while (null == be)
  1981. {
  1982. current = parent;
  1983. parent = parent.ParentNode;
  1984. if (parent == null || !(parent is Expression))
  1985. return false;
  1986. be = parent as BinaryExpression;
  1987. }
  1988. return be.Left == current;
  1989. }
  1990. private bool IsWriteOnlyProperty(IProperty property)
  1991. {
  1992. return null == property.GetGetMethod();
  1993. }
  1994. private IEntity ResolveAmbiguousLValue(Expression sourceNode, Ambiguous candidates, Expression rvalue)
  1995. {
  1996. if (!candidates.AllEntitiesAre(EntityType.Property)) return null;
  1997. IEntity[] entities = candidates.Entities;
  1998. IEntity[] getters = GetSetMethods(entities);
  1999. ExpressionCollection args = new ExpressionCollection();
  2000. args.Add(rvalue);
  2001. IEntity found = GetCorrectCallableReference(sourceNode, args, getters);
  2002. if (null != found && EntityType.Method == found.EntityType)
  2003. {
  2004. IProperty property = (IProperty)entities[GetIndex(getters, found)];
  2005. BindProperty(sourceNode, property);
  2006. return property;
  2007. }
  2008. return null;
  2009. }
  2010. private static void BindProperty(Expression expression, IProperty property)
  2011. {
  2012. expression.Entity = property;
  2013. expression.ExpressionType = property.Type;
  2014. }
  2015. private IEntity ResolveAmbiguousReference(ReferenceExpression node, Ambiguous candidates)
  2016. {
  2017. var resolved = ResolveAmbiguousReferenceByAccessibility(candidates);
  2018. var accessibleCandidates = resolved as Ambiguous;
  2019. if (accessibleCandidates == null || AstUtil.IsTargetOfSlicing(node) || node.IsTargetOfAssignment())
  2020. return resolved;
  2021. if (accessibleCandidates.AllEntitiesAre(EntityType.Property))
  2022. return ResolveAmbiguousPropertyReference(node, accessibleCandidates, EmptyExpressionCollection);
  2023. if (accessibleCandidates.AllEntitiesAre(EntityType.Method))
  2024. return ResolveAmbiguousMethodReference(node, accessibleCandidates, EmptyExpressionCollection);
  2025. if (accessibleCandidates.AllEntitiesAre(EntityType.Type))
  2026. return ResolveAmbiguousTypeReference(node, accessibleCandidates);
  2027. return resolved;
  2028. }
  2029. private IEntity ResolveAmbiguousMethodReference(ReferenceExpression node, Ambiguous candidates, ExpressionCollection args)
  2030. {
  2031. //BOO-656
  2032. if (!AstUtil.IsTargetOfMethodInvocation(node)
  2033. && !AstUtil.IsTargetOfSlicing(node)
  2034. && !node.IsTargetOfAssignment())
  2035. {
  2036. return candidates.Entities[0];
  2037. }
  2038. return candidates;
  2039. }
  2040. private IEntity ResolveAmbiguousPropertyReference(ReferenceExpression node, Ambiguous candidates, ExpressionCollection args)
  2041. {
  2042. IEntity[] entities = candidates.Entities;
  2043. IEntity[] getters = GetGetMethods(entities);
  2044. IEntity found = GetCorrectCallableReference(node, args, getters);
  2045. if (null != found && EntityType.Method == found.EntityType)
  2046. {
  2047. IProperty property = (IProperty)entities[GetIndex(getters, found)];
  2048. BindProperty(node, property);
  2049. return property;
  2050. }
  2051. return candidates;
  2052. }
  2053. private IEntity ResolveAmbiguousTypeReference(ReferenceExpression node, Ambiguous candidates)
  2054. {
  2055. List<IEntity> matches = GetMatchesByGenericity(node, candidates);
  2056. if (matches.Count > 1)
  2057. {
  2058. PreferInternalEntitiesOverNonInternal(matches);
  2059. }
  2060. if (matches.Count == 1)
  2061. {
  2062. Bind(node, matches[0]);
  2063. }
  2064. else
  2065. {
  2066. Bind(node, new Ambiguous(matches));
  2067. }
  2068. return node.Entity;
  2069. }
  2070. private static void PreferInternalEntitiesOverNonInternal(List<IEntity> matches)
  2071. {
  2072. bool isAmbiguousBetweenInternalAndExternalEntities = matches.Contains(EntityPredicates.IsInternalEntity) &&
  2073. matches.Contains(EntityPredicates.IsNonInternalEntity);
  2074. if (isAmbiguousBetweenInternalAndExternalEntities)
  2075. matches.RemoveAll(EntityPredicates.IsNonInternalEntity);
  2076. }
  2077. private List<IEntity> GetMatchesByGenericity(ReferenceExpression node, Ambiguous candidates)
  2078. {
  2079. bool isGenericReference = (node.ParentNode is GenericReferenceExpression);
  2080. List<IEntity> matches = new List<IEntity>();
  2081. foreach (IEntity candidate in candidates.Entities)
  2082. {
  2083. IType type = candidate as IType;
  2084. bool isGenericType = (type != null && type.GenericInfo != null);
  2085. if (isGenericType == isGenericReference)
  2086. {
  2087. matches.Add(candidate);
  2088. }
  2089. }
  2090. return matches;
  2091. }
  2092. private IEntity ResolveAmbiguousReferenceByAccessibility(Ambiguous candidates)
  2093. {
  2094. var newEntities = new List<IEntity>();
  2095. foreach (IEntity entity in candidates.Entities)
  2096. if (!IsInaccessible(entity))
  2097. newEntities.Add(entity);
  2098. return Entities.EntityFromList(newEntities);
  2099. }
  2100. private int GetIndex(IEntity[] entities, IEntity entity)
  2101. {
  2102. for (int i=0; i<entities.Length; ++i)
  2103. if (entities[i] == entity) return i;
  2104. throw new ArgumentException("entity");
  2105. }
  2106. override public void LeaveConditionalExpression(ConditionalExpression node)
  2107. {
  2108. var trueType = GetExpressionType(node.TrueValue);
  2109. var falseType = GetExpressionType(node.FalseValue);
  2110. BindExpressionType(node, GetMostGenericType(trueType, falseType));
  2111. }
  2112. override public void LeaveYieldStatement(YieldStatement node)
  2113. {
  2114. if (EntityType.Constructor == _currentMethod.EntityType)
  2115. {
  2116. Error(CompilerErrorFactory.YieldInsideConstructor(node));
  2117. return;
  2118. }
  2119. _currentMethod.AddYieldStatement(node);
  2120. }
  2121. override public void LeaveReturnStatement(ReturnStatement node)
  2122. {
  2123. if (null == node.Expression)
  2124. return;
  2125. // forces anonymous types to be correctly
  2126. // instantiated
  2127. IType expressionType = GetConcreteExpressionType(node.Expression);
  2128. if (TypeSystemServices.VoidType == expressionType
  2129. && node.ContainsAnnotation(OptionalReturnStatementAnnotation))
  2130. {
  2131. node.ParentNode.Replace(
  2132. node,
  2133. new ExpressionStatement(node.Expression));
  2134. return;
  2135. }
  2136. IType returnType = _currentMethod.ReturnType;
  2137. if (TypeSystemServices.IsUnknown(returnType))
  2138. _currentMethod.AddReturnExpression(node.Expression);
  2139. else
  2140. AssertTypeCompatibility(node.Expression, returnType, expressionType);
  2141. //bind to nullable Value if needed
  2142. if (TypeSystemServices.IsNullable(expressionType) && !TypeSystemServices.IsNullable(returnType))
  2143. {
  2144. // TODO: move to later steps or introduce an implicit conversion operator
  2145. var mre = new MemberReferenceExpression(node.Expression.LexicalInfo, node.Expression, "Value");
  2146. Visit(mre);
  2147. node.Replace(node.Expression, mre);
  2148. }
  2149. }
  2150. protected Expression GetCorrectIterator(Expression iterator)
  2151. {
  2152. IType type = GetExpressionType(iterator);
  2153. if (IsError(type))
  2154. return iterator;
  2155. if (!IsAssignableFrom(TypeSystemServices.IEnumerableType, type) &&
  2156. !IsAssignableFrom(TypeSystemServices.IEnumeratorType, type))
  2157. {
  2158. if (IsRuntimeIterator(type))
  2159. return IsTextReader(type)
  2160. ? CodeBuilder.CreateMethodInvocation(MethodCache.TextReaderEnumerator_lines, iterator)
  2161. : CodeBuilder.CreateMethodInvocation(MethodCache.RuntimeServices_GetEnumerable, iterator);
  2162. }
  2163. return iterator;
  2164. }
  2165. protected RuntimeMethodCache MethodCache
  2166. {
  2167. get { return _methodCache; }
  2168. }
  2169. private EnvironmentProvision<RuntimeMethodCache> _methodCache;
  2170. /// <summary>
  2171. /// Process a iterator and its declarations and returns a new iterator
  2172. /// expression if necessary.
  2173. /// </summary>
  2174. protected Expression ProcessIterator(Expression iterator, DeclarationCollection declarations)
  2175. {
  2176. iterator = GetCorrectIterator(iterator);
  2177. ProcessDeclarationsForIterator(declarations, GetExpressionType(iterator));
  2178. return iterator;
  2179. }
  2180. public override void OnGotoStatement(GotoStatement node)
  2181. {
  2182. // don't try to resolve label references
  2183. }
  2184. override public void OnForStatement(ForStatement node)
  2185. {
  2186. Visit(node.Iterator);
  2187. node.Iterator = ProcessIterator(node.Iterator, node.Declarations);
  2188. VisitForStatementBlock(node);
  2189. }
  2190. protected void VisitForStatementBlock(ForStatement node)
  2191. {
  2192. EnterForNamespace(node);
  2193. Visit(node.Block);
  2194. Visit(node.OrBlock);
  2195. Visit(node.ThenBlock);
  2196. LeaveNamespace();
  2197. }
  2198. private void EnterForNamespace(ForStatement node)
  2199. {
  2200. EnterNamespace(new DeclarationsNamespace(CurrentNamespace, node.Declarations));
  2201. }
  2202. override public void OnUnpackStatement(UnpackStatement node)
  2203. {
  2204. Visit(node.Expression);
  2205. node.Expression = GetCorrectIterator(node.Expression);
  2206. IType defaultDeclarationType = GetEnumeratorItemType(GetExpressionType(node.Expression));
  2207. foreach (Declaration d in node.Declarations)
  2208. {
  2209. bool declareNewVariable = d.Type != null;
  2210. GetDeclarationType(defaultDeclarationType, d);
  2211. if (declareNewVariable)
  2212. {
  2213. AssertUniqueLocal(d);
  2214. }
  2215. else
  2216. {
  2217. IEntity entity = TryToResolveName(d.Name);
  2218. if (null != entity)
  2219. {
  2220. Bind(d, entity);
  2221. AssertLValue(d, entity);
  2222. continue;
  2223. }
  2224. }
  2225. DeclareLocal(d, false);
  2226. }
  2227. }
  2228. override public void LeaveRaiseStatement(RaiseStatement node)
  2229. {
  2230. if (node.Exception == null) return;
  2231. var exceptionType = GetExpressionType(node.Exception);
  2232. if (IsError(exceptionType))
  2233. return;
  2234. if (TypeSystemServices.StringType == exceptionType)
  2235. {
  2236. node.Exception = CodeBuilder.CreateConstructorInvocation(
  2237. node.Exception.LexicalInfo,
  2238. MethodCache.Exception_StringConstructor,
  2239. node.Exception);
  2240. }
  2241. else if (!TypeSystemServices.IsValidException(exceptionType))
  2242. {
  2243. Error(CompilerErrorFactory.InvalidRaiseArgument(node.Exception, exceptionType));
  2244. }
  2245. }
  2246. override public void OnExceptionHandler(ExceptionHandler node)
  2247. {
  2248. bool untypedException = (node.Flags & ExceptionHandlerFlags.Untyped) == ExceptionHandlerFlags.Untyped;
  2249. bool anonymousException = (node.Flags & ExceptionHandlerFlags.Anonymous) == ExceptionHandlerFlags.Anonymous;
  2250. bool filterHandler = (node.Flags & ExceptionHandlerFlags.Filter) == ExceptionHandlerFlags.Filter;
  2251. if (untypedException)
  2252. {
  2253. // If untyped, set the handler to except System.Exception
  2254. node.Declaration.Type = CodeBuilder.CreateTypeReference(TypeSystemServices.ExceptionType);
  2255. }
  2256. else
  2257. {
  2258. Visit(node.Declaration.Type);
  2259. // Require typed exception handlers to except only
  2260. // exceptions at least as derived as System.Exception
  2261. if(!TypeSystemServices.IsValidException(GetType(node.Declaration.Type)))
  2262. {
  2263. Errors.Add(CompilerErrorFactory.InvalidExceptArgument(node.Declaration.Type, GetType(node.Declaration.Type)));
  2264. }
  2265. }
  2266. if(!anonymousException)
  2267. {
  2268. // If the exception is not anonymous, place it into a
  2269. // local variable and enter a new namespace
  2270. DeclareLocal(node.Declaration, true);
  2271. EnterNamespace(new DeclarationsNamespace(CurrentNamespace, node.Declaration));
  2272. }
  2273. try
  2274. {
  2275. // The filter handler has access to the exception if it
  2276. // is not anonymous, so it is protected to ensure
  2277. // any exception in the filter condition (a big no-no)
  2278. // will still clean up the namespace if necessary
  2279. if (filterHandler)
  2280. {
  2281. Visit(node.FilterCondition);
  2282. }
  2283. Visit(node.Block);
  2284. }
  2285. finally
  2286. {
  2287. // Clean up the namespace if necessary
  2288. if(!anonymousException)
  2289. {
  2290. LeaveNamespace();
  2291. }
  2292. }
  2293. }
  2294. protected virtual bool IsValidIncrementDecrementOperand(Expression e)
  2295. {
  2296. IType type = GetExpressionType(e);
  2297. if (type.IsPointer)
  2298. return true;
  2299. if (TypeSystemServices.IsNullable(type))
  2300. type = TypeSystemServices.GetNullableUnderlyingType(type);
  2301. return TypeSystemServices.IsNumber(type) || TypeSystemServices.IsDuckType(type);
  2302. }
  2303. void LeaveIncrementDecrement(UnaryExpression node)
  2304. {
  2305. if (AssertLValue(node.Operand))
  2306. {
  2307. if (!IsValidIncrementDecrementOperand(node.Operand))
  2308. InvalidOperatorForType(node);
  2309. else
  2310. ExpandIncrementDecrement(node);
  2311. }
  2312. else
  2313. Error(node);
  2314. }
  2315. void ExpandIncrementDecrement(UnaryExpression node)
  2316. {
  2317. var expansion = IsArraySlicing(node.Operand)
  2318. ? ExpandIncrementDecrementArraySlicing(node)
  2319. : ExpandSimpleIncrementDecrement(node);
  2320. node.ParentNode.Replace(node, expansion);
  2321. Visit(expansion);
  2322. }
  2323. Expression ExpandIncrementDecrementArraySlicing(UnaryExpression node)
  2324. {
  2325. SlicingExpression slicing = (SlicingExpression)node.Operand;
  2326. AssertIsNotComplexSlicing(slicing);
  2327. Visit(slicing);
  2328. return CreateSideEffectAwareSlicingOperation(
  2329. node.LexicalInfo,
  2330. GetEquivalentBinaryOperator(node.Operator),
  2331. slicing,
  2332. CodeBuilder.CreateIntegerLiteral(1),
  2333. DeclareOldValueTempIfNeeded(node));
  2334. }
  2335. private Expression CreateSideEffectAwareSlicingOperation(LexicalInfo lexicalInfo, BinaryOperatorType binaryOperator, SlicingExpression lvalue, Expression rvalue, InternalLocal returnValue)
  2336. {
  2337. MethodInvocationExpression eval = CodeBuilder.CreateEvalInvocation(lexicalInfo);
  2338. if (HasSideEffect(lvalue.Target))
  2339. {
  2340. InternalLocal temp = AddInitializedTempLocal(eval, lvalue.Target);
  2341. lvalue.Target = CodeBuilder.CreateReference(temp);
  2342. }
  2343. foreach (Slice slice in lvalue.Indices)
  2344. {
  2345. Expression index = slice.Begin;
  2346. if (HasSideEffect(index))
  2347. {
  2348. InternalLocal temp = AddInitializedTempLocal(eval, index);
  2349. slice.Begin = CodeBuilder.CreateReference(temp);
  2350. }
  2351. }
  2352. BinaryExpression addition = CodeBuilder.CreateBoundBinaryExpression(
  2353. GetExpressionType(lvalue),
  2354. binaryOperator,
  2355. CloneOrAssignToTemp(returnValue, lvalue),
  2356. rvalue);
  2357. Expression expansion = CodeBuilder.CreateAssignment(
  2358. lvalue.CloneNode(),
  2359. addition);
  2360. // Resolve operator overloads if any
  2361. BindArithmeticOperator(addition);
  2362. if (eval.Arguments.Count > 0 || null != returnValue)
  2363. {
  2364. eval.Arguments.Add(expansion);
  2365. if (null != returnValue)
  2366. {
  2367. eval.Arguments.Add(CodeBuilder.CreateReference(returnValue));
  2368. }
  2369. BindExpressionType(eval, GetExpressionType(lvalue));
  2370. expansion = eval;
  2371. }
  2372. return expansion;
  2373. }
  2374. InternalLocal AddInitializedTempLocal(MethodInvocationExpression eval, Expression initializer)
  2375. {
  2376. InternalLocal temp = DeclareTempLocal(GetExpressionType(initializer));
  2377. eval.Arguments.Add(
  2378. CodeBuilder.CreateAssignment(
  2379. CodeBuilder.CreateReference(temp),
  2380. initializer));
  2381. return temp;
  2382. }
  2383. InternalLocal DeclareOldValueTempIfNeeded(UnaryExpression node)
  2384. {
  2385. return AstUtil.IsPostUnaryOperator(node.Operator)
  2386. ? DeclareTempLocal(GetExpressionType(node.Operand))
  2387. : null;
  2388. }
  2389. Expression ExpandSimpleIncrementDecrement(UnaryExpression node)
  2390. {
  2391. var oldValue = DeclareOldValueTempIfNeeded(node);
  2392. var type = GetExpressionType(node.Operand);
  2393. var addition = CodeBuilder.CreateBoundBinaryExpression(
  2394. type,
  2395. GetEquivalentBinaryOperator(node.Operator),
  2396. CloneOrAssignToTemp(oldValue, node.Operand),
  2397. CodeBuilder.CreateIntegerLiteral(1));
  2398. var assign = CodeBuilder.CreateAssignment(
  2399. node.LexicalInfo,
  2400. node.Operand,
  2401. addition);
  2402. // Resolve operator overloads if any
  2403. BindArithmeticOperator(addition);
  2404. return oldValue == null
  2405. ? (Expression) assign
  2406. : CodeBuilder.CreateEvalInvocation(
  2407. node.LexicalInfo,
  2408. assign,
  2409. CodeBuilder.CreateReference(oldValue));
  2410. }
  2411. Expression CloneOrAssignToTemp(InternalLocal temp, Expression operand)
  2412. {
  2413. return null == temp
  2414. ? operand.CloneNode()
  2415. : CodeBuilder.CreateAssignment(
  2416. CodeBuilder.CreateReference(temp),
  2417. operand.CloneNode());
  2418. }
  2419. static BinaryOperatorType GetEquivalentBinaryOperator(UnaryOperatorType op)
  2420. {
  2421. switch (op)
  2422. {
  2423. case UnaryOperatorType.PostIncrement:
  2424. case UnaryOperatorType.Increment:
  2425. return BinaryOperatorType.Addition;
  2426. case UnaryOperatorType.PostDecrement:
  2427. case UnaryOperatorType.Decrement:
  2428. return BinaryOperatorType.Subtraction;
  2429. }
  2430. throw new ArgumentException("op");
  2431. }
  2432. static UnaryOperatorType GetRelatedPreOperator(UnaryOperatorType op)
  2433. {
  2434. switch (op)
  2435. {
  2436. case UnaryOperatorType.PostIncrement:
  2437. return UnaryOperatorType.Increment;
  2438. case UnaryOperatorType.PostDecrement:
  2439. return UnaryOperatorType.Decrement;
  2440. }
  2441. throw new ArgumentException("op");
  2442. }
  2443. override public bool EnterUnaryExpression(UnaryExpression node)
  2444. {
  2445. if (AstUtil.IsPostUnaryOperator(node.Operator) && NodeType.ExpressionStatement == node.ParentNode.NodeType)
  2446. {
  2447. // nothing to do, a post operator inside a statement
  2448. // behaves just like its equivalent pre operator
  2449. node.Operator = GetRelatedPreOperator(node.Operator);
  2450. }
  2451. return true;
  2452. }
  2453. override public void LeaveUnaryExpression(UnaryExpression node)
  2454. {
  2455. switch (node.Operator)
  2456. {
  2457. case UnaryOperatorType.Explode:
  2458. {
  2459. LeaveExplodeExpression(node);
  2460. break;
  2461. }
  2462. case UnaryOperatorType.LogicalNot:
  2463. {
  2464. LeaveLogicalNot(node);
  2465. break;
  2466. }
  2467. case UnaryOperatorType.Increment:
  2468. case UnaryOperatorType.PostIncrement:
  2469. case UnaryOperatorType.Decrement:
  2470. case UnaryOperatorType.PostDecrement:
  2471. {
  2472. LeaveIncrementDecrement(node);
  2473. break;
  2474. }
  2475. case UnaryOperatorType.UnaryNegation:
  2476. {
  2477. LeaveUnaryNegation(node);
  2478. break;
  2479. }
  2480. case UnaryOperatorType.OnesComplement:
  2481. {
  2482. LeaveOnesComplement(node);
  2483. break;
  2484. }
  2485. case UnaryOperatorType.AddressOf:
  2486. {
  2487. LeaveAddressOf(node);
  2488. break;
  2489. }
  2490. case UnaryOperatorType.Indirection:
  2491. {
  2492. LeaveIndirection(node);
  2493. break;
  2494. }
  2495. default:
  2496. {
  2497. NotImplemented(node, "unary operator not supported");
  2498. break;
  2499. }
  2500. }
  2501. }
  2502. private void LeaveOnesComplement(UnaryExpression node)
  2503. {
  2504. if (IsPrimitiveOnesComplementOperand(node.Operand))
  2505. BindExpressionType(node, GetExpressionType(node.Operand));
  2506. else
  2507. ProcessOperatorOverload(node);
  2508. }
  2509. private bool IsPrimitiveOnesComplementOperand(Expression operand)
  2510. {
  2511. IType type = GetExpressionType(operand);
  2512. return TypeSystemServices.IsIntegerNumber(type) || type.IsEnum;
  2513. }
  2514. private void LeaveLogicalNot(UnaryExpression node)
  2515. {
  2516. BindExpressionType(node, TypeSystemServices.BoolType);
  2517. }
  2518. private void LeaveUnaryNegation(UnaryExpression node)
  2519. {
  2520. if (IsPrimitiveNumber(node.Operand))
  2521. BindExpressionType(node, GetExpressionType(node.Operand));
  2522. else
  2523. ProcessOperatorOverload(node);
  2524. }
  2525. private void LeaveAddressOf(UnaryExpression node)
  2526. {
  2527. IType dataType = GetExpressionType(node.Operand);
  2528. if (dataType.IsArray) //if array reference take address of first element
  2529. {
  2530. dataType = dataType.ElementType;
  2531. node.Replace(node.Operand, new SlicingExpression(node.Operand, new IntegerLiteralExpression(0)));
  2532. BindExpressionType(node.Operand, dataType);
  2533. }
  2534. if (TypeSystemServices.IsPointerCompatible(dataType))
  2535. {
  2536. node.Entity = dataType.MakePointerType();
  2537. BindExpressionType(node, dataType.MakePointerType());
  2538. return;
  2539. }
  2540. BindExpressionType(node, TypeSystemServices.ErrorEntity);
  2541. Error(CompilerErrorFactory.PointerIncompatibleType(node.Operand, dataType));
  2542. }
  2543. private void LeaveIndirection(UnaryExpression node)
  2544. {
  2545. if (TypeSystemServices.IsError(node.Operand))
  2546. return;
  2547. IType dataType = GetExpressionType(node.Operand).ElementType;
  2548. if (null != dataType && TypeSystemServices.IsPointerCompatible(dataType))
  2549. {
  2550. node.Entity = node.Operand.Entity;
  2551. BindExpressionType(node, dataType);
  2552. return;
  2553. }
  2554. BindExpressionType(node, TypeSystemServices.ErrorEntity);
  2555. Error(CompilerErrorFactory.PointerIncompatibleType(node.Operand, dataType));
  2556. }
  2557. private void ProcessOperatorOverload(UnaryExpression node)
  2558. {
  2559. if (! ResolveOperator(node))
  2560. {
  2561. InvalidOperatorForType(node);
  2562. }
  2563. }
  2564. override public bool EnterBinaryExpression(BinaryExpression node)
  2565. {
  2566. if (BinaryOperatorType.Assign != node.Operator)
  2567. return true;
  2568. if (NodeType.ReferenceExpression != node.Left.NodeType)
  2569. return true;
  2570. if (node.Left.Entity != null)
  2571. return true;
  2572. // Auto local declaration:
  2573. // assign to unknown reference implies local
  2574. // declaration
  2575. ReferenceExpression reference = (ReferenceExpression)node.Left;
  2576. IEntity entity = TryToResolveName(reference.Name);
  2577. if (null == entity || TypeSystemServices.IsBuiltin(entity) || IsInaccessible(entity))
  2578. {
  2579. ProcessAutoLocalDeclaration(node, reference);
  2580. return false;
  2581. }
  2582. return true;
  2583. }
  2584. protected virtual void ProcessAutoLocalDeclaration(BinaryExpression node, ReferenceExpression reference)
  2585. {
  2586. Visit(node.Right);
  2587. IType expressionType = MapWildcardType(GetConcreteExpressionType(node.Right));
  2588. IEntity local = DeclareLocal(reference, reference.Name, expressionType);
  2589. reference.Entity = local;
  2590. BindExpressionType(reference, expressionType);
  2591. BindExpressionType(node, expressionType);
  2592. }
  2593. bool IsInaccessible(IEntity info)
  2594. {
  2595. var accessible = info as IAccessibleMember;
  2596. if (accessible != null && accessible.IsPrivate && accessible.DeclaringType != CurrentType)
  2597. return true;
  2598. return false;
  2599. }
  2600. override public void LeaveBinaryExpression(BinaryExpression node)
  2601. {
  2602. if (TypeSystemServices.IsUnknown(node.Left) || TypeSystemServices.IsUnknown(node.Right))
  2603. {
  2604. BindExpressionType(node, Unknown.Default);
  2605. return;
  2606. }
  2607. if (TypeSystemServices.IsError(node.Left) || TypeSystemServices.IsError(node.Right))
  2608. {
  2609. Error(node);
  2610. return;
  2611. }
  2612. BindBinaryExpression(node);
  2613. }
  2614. protected virtual void BindBinaryExpression(BinaryExpression node)
  2615. {
  2616. if (IsEnumOperation(node))
  2617. {
  2618. BindEnumOperation(node);
  2619. return;
  2620. }
  2621. switch (node.Operator)
  2622. {
  2623. case BinaryOperatorType.Assign:
  2624. {
  2625. BindAssignment(node);
  2626. break;
  2627. }
  2628. case BinaryOperatorType.Addition:
  2629. {
  2630. if (GetExpressionType(node.Left).IsArray && GetExpressionType(node.Right).IsArray)
  2631. BindArrayAddition(node);
  2632. else
  2633. BindArithmeticOperator(node);
  2634. break;
  2635. }
  2636. case BinaryOperatorType.Subtraction:
  2637. case BinaryOperatorType.Multiply:
  2638. case BinaryOperatorType.Division:
  2639. case BinaryOperatorType.Modulus:
  2640. case BinaryOperatorType.Exponentiation:
  2641. {
  2642. BindArithmeticOperator(node);
  2643. break;
  2644. }
  2645. case BinaryOperatorType.TypeTest:
  2646. {
  2647. BindTypeTest(node);
  2648. break;
  2649. }
  2650. case BinaryOperatorType.ReferenceEquality:
  2651. {
  2652. BindReferenceEquality(node);
  2653. break;
  2654. }
  2655. case BinaryOperatorType.ReferenceInequality:
  2656. {
  2657. BindReferenceEquality(node, true);
  2658. break;
  2659. }
  2660. case BinaryOperatorType.Or:
  2661. case BinaryOperatorType.And:
  2662. {
  2663. BindExpressionType(node, GetMostGenericType(node));
  2664. break;
  2665. }
  2666. case BinaryOperatorType.BitwiseAnd:
  2667. case BinaryOperatorType.BitwiseOr:
  2668. case BinaryOperatorType.ExclusiveOr:
  2669. case BinaryOperatorType.ShiftLeft:
  2670. case BinaryOperatorType.ShiftRight:
  2671. {
  2672. BindBitwiseOperator(node);
  2673. break;
  2674. }
  2675. case BinaryOperatorType.InPlaceSubtraction:
  2676. case BinaryOperatorType.InPlaceAddition:
  2677. {
  2678. BindInPlaceAddSubtract(node);
  2679. break;
  2680. }
  2681. case BinaryOperatorType.InPlaceShiftLeft:
  2682. case BinaryOperatorType.InPlaceShiftRight:
  2683. case BinaryOperatorType.InPlaceDivision:
  2684. case BinaryOperatorType.InPlaceMultiply:
  2685. case BinaryOperatorType.InPlaceModulus:
  2686. case BinaryOperatorType.InPlaceBitwiseOr:
  2687. case BinaryOperatorType.InPlaceBitwiseAnd:
  2688. case BinaryOperatorType.InPlaceExclusiveOr:
  2689. {
  2690. BindInPlaceArithmeticOperator(node);
  2691. break;
  2692. }
  2693. case BinaryOperatorType.GreaterThan:
  2694. case BinaryOperatorType.GreaterThanOrEqual:
  2695. case BinaryOperatorType.LessThan:
  2696. case BinaryOperatorType.LessThanOrEqual:
  2697. case BinaryOperatorType.Inequality:
  2698. case BinaryOperatorType.Equality:
  2699. {
  2700. BindCmpOperator(node);
  2701. break;
  2702. }
  2703. default:
  2704. {
  2705. if (!ResolveOperator(node))
  2706. {
  2707. InvalidOperatorForTypes(node);
  2708. }
  2709. break;
  2710. }
  2711. }
  2712. }
  2713. IType GetMostGenericType(BinaryExpression node)
  2714. {
  2715. return GetMostGenericType(GetExpressionType(node.Left), GetExpressionType(node.Right));
  2716. }
  2717. bool IsNullableOperation(BinaryExpression node)
  2718. {
  2719. if (null == node.Left.ExpressionType || null == node.Right.ExpressionType)
  2720. {
  2721. return false;
  2722. }
  2723. return TypeSystemServices.IsNullable(GetExpressionType(node.Left))
  2724. || TypeSystemServices.IsNullable(GetExpressionType(node.Right));
  2725. }
  2726. bool IsEnumOperation(BinaryExpression node)
  2727. {
  2728. switch (node.Operator)
  2729. {
  2730. case BinaryOperatorType.Addition:
  2731. case BinaryOperatorType.Subtraction:
  2732. case BinaryOperatorType.BitwiseAnd:
  2733. case BinaryOperatorType.BitwiseOr:
  2734. case BinaryOperatorType.ExclusiveOr:
  2735. IType lhs = GetExpressionType(node.Left);
  2736. IType rhs = GetExpressionType(node.Right);
  2737. if (lhs.IsEnum) return IsValidEnumOperand(lhs, rhs);
  2738. if (rhs.IsEnum) return IsValidEnumOperand(rhs, lhs);
  2739. break;
  2740. }
  2741. return false;
  2742. }
  2743. bool IsValidEnumOperand(IType expected, IType actual)
  2744. {
  2745. if (expected == actual) return true;
  2746. if (actual.IsEnum) return true;
  2747. return TypeSystemServices.IsIntegerNumber(actual);
  2748. }
  2749. void BindEnumOperation(BinaryExpression node)
  2750. {
  2751. IType lhs = GetExpressionType(node.Left);
  2752. IType rhs = GetExpressionType(node.Right);
  2753. switch(node.Operator)
  2754. {
  2755. case BinaryOperatorType.Addition:
  2756. if (lhs.IsEnum != rhs.IsEnum)
  2757. {
  2758. BindExpressionType(node, lhs.IsEnum ? lhs : rhs);
  2759. return;
  2760. }
  2761. break;
  2762. case BinaryOperatorType.Subtraction:
  2763. if (lhs == rhs)
  2764. {
  2765. BindExpressionType(node, TypeSystemServices.IntType);
  2766. return;
  2767. }
  2768. else if (lhs.IsEnum && !rhs.IsEnum)
  2769. {
  2770. BindExpressionType(node, lhs);
  2771. return;
  2772. }
  2773. break;
  2774. case BinaryOperatorType.BitwiseAnd:
  2775. case BinaryOperatorType.BitwiseOr:
  2776. case BinaryOperatorType.ExclusiveOr:
  2777. if (lhs == rhs)
  2778. {
  2779. BindExpressionType(node, lhs);
  2780. return;
  2781. }
  2782. break;
  2783. }
  2784. if (!ResolveOperator(node))
  2785. {
  2786. InvalidOperatorForTypes(node);
  2787. }
  2788. }
  2789. void BindBitwiseOperator(BinaryExpression node)
  2790. {
  2791. IType lhs = GetExpressionType(node.Left);
  2792. IType rhs = GetExpressionType(node.Right);
  2793. if (TypeSystemServices.IsIntegerOrBool(lhs) &&
  2794. TypeSystemServices.IsIntegerOrBool(rhs))
  2795. {
  2796. IType type;
  2797. switch (node.Operator)
  2798. {
  2799. case BinaryOperatorType.ShiftLeft:
  2800. case BinaryOperatorType.ShiftRight:
  2801. type = lhs;
  2802. break;
  2803. default:
  2804. type = TypeSystemServices.GetPromotedNumberType(lhs, rhs);
  2805. break;
  2806. }
  2807. BindExpressionType(node, type);
  2808. }
  2809. else
  2810. {
  2811. // if (lhs.IsEnum && rhs == lhs)
  2812. // {
  2813. // BindExpressionType(node, lhs);
  2814. // }
  2815. // else
  2816. // {
  2817. if (!ResolveOperator(node))
  2818. {
  2819. InvalidOperatorForTypes(node);
  2820. }
  2821. // }
  2822. }
  2823. }
  2824. bool IsChar(IType type)
  2825. {
  2826. return TypeSystemServices.CharType == type;
  2827. }
  2828. void BindCmpOperator(BinaryExpression node)
  2829. {
  2830. if (BindNullableComparison(node))
  2831. {
  2832. return;
  2833. }
  2834. IType lhs = GetExpressionType(node.Left);
  2835. IType rhs = GetExpressionType(node.Right);
  2836. if (IsPrimitiveComparison(lhs, rhs))
  2837. {
  2838. BindExpressionType(node, TypeSystemServices.BoolType);
  2839. return;
  2840. }
  2841. if (lhs.IsEnum || rhs.IsEnum)
  2842. {
  2843. if (lhs == rhs
  2844. || TypeSystemServices.IsPrimitiveNumber(rhs)
  2845. || TypeSystemServices.IsPrimitiveNumber(lhs))
  2846. {
  2847. BindExpressionType(node, TypeSystemServices.BoolType);
  2848. }
  2849. else
  2850. {
  2851. if (!ResolveOperator(node))
  2852. {
  2853. InvalidOperatorForTypes(node);
  2854. }
  2855. }
  2856. return;
  2857. }
  2858. if (!ResolveOperator(node))
  2859. {
  2860. switch (node.Operator)
  2861. {
  2862. case BinaryOperatorType.Equality:
  2863. {
  2864. if (OptimizeNullComparisons
  2865. && (IsNull(node.Left) || IsNull(node.Right)))
  2866. {
  2867. node.Operator = BinaryOperatorType.ReferenceEquality;
  2868. BindReferenceEquality(node);
  2869. break;
  2870. }
  2871. Expression expression = CreateEquals(node);
  2872. node.ParentNode.Replace(node, expression);
  2873. break;
  2874. }
  2875. case BinaryOperatorType.Inequality:
  2876. {
  2877. if (OptimizeNullComparisons
  2878. && (IsNull(node.Left) || IsNull(node.Right)))
  2879. {
  2880. node.Operator = BinaryOperatorType.ReferenceInequality;
  2881. BindReferenceEquality(node, true);
  2882. break;
  2883. }
  2884. Expression expression = CreateEquals(node);
  2885. Node parent = node.ParentNode;
  2886. parent.Replace(node, CodeBuilder.CreateNotExpression(expression));
  2887. break;
  2888. }
  2889. default:
  2890. {
  2891. InvalidOperatorForTypes(node);
  2892. break;
  2893. }
  2894. }
  2895. }
  2896. }
  2897. private bool IsPrimitiveComparison(IType lhs, IType rhs)
  2898. {
  2899. if (IsPrimitiveNumberOrChar(lhs) && IsPrimitiveNumberOrChar(rhs)) return true;
  2900. if (IsBool(lhs) && IsBool(rhs)) return true;
  2901. return false;
  2902. }
  2903. private bool IsPrimitiveNumberOrChar(IType lhs)
  2904. {
  2905. return TypeSystemServices.IsPrimitiveNumber(lhs) || IsChar(lhs);
  2906. }
  2907. private bool IsBool(IType lhs)
  2908. {
  2909. return TypeSystemServices.BoolType == lhs;
  2910. }
  2911. private static bool IsNull(Expression node)
  2912. {
  2913. return NodeType.NullLiteralExpression == node.NodeType;
  2914. }
  2915. void BindInPlaceAddSubtract(BinaryExpression node)
  2916. {
  2917. if (IsEventSubscription(node))
  2918. {
  2919. BindEventSubscription(node);
  2920. return;
  2921. }
  2922. BindInPlaceArithmeticOperator(node);
  2923. }
  2924. static bool IsEventSubscription(BinaryExpression node)
  2925. {
  2926. var leftEntity = node.Left.Entity;
  2927. return leftEntity != null
  2928. && (IsEvent(leftEntity) || leftEntity.IsAmbiguous());
  2929. }
  2930. static bool IsEvent(IEntity entity)
  2931. {
  2932. return EntityType.Event == entity.EntityType;
  2933. }
  2934. void BindEventSubscription(BinaryExpression node)
  2935. {
  2936. IEntity entity = GetEntity(node.Left);
  2937. if (entity.IsAmbiguous())
  2938. {
  2939. IList found = ((Ambiguous) entity).Select(IsPublicEvent);
  2940. if (found.Count != 1)
  2941. {
  2942. Error(node);
  2943. return;
  2944. }
  2945. entity = (IEntity) found[0];
  2946. Bind(node.Left, entity);
  2947. }
  2948. IEvent eventInfo = (IEvent)entity;
  2949. IType rtype = GetExpressionType(node.Right);
  2950. if (!AssertDelegateArgument(node, eventInfo, rtype))
  2951. {
  2952. Error(node);
  2953. return;
  2954. }
  2955. BindExpressionType(node, TypeSystemServices.VoidType);
  2956. }
  2957. virtual protected void ProcessBuiltinInvocation(MethodInvocationExpression node, BuiltinFunction function)
  2958. {
  2959. switch (function.FunctionType)
  2960. {
  2961. case BuiltinFunctionType.Len:
  2962. {
  2963. ProcessLenInvocation(node);
  2964. break;
  2965. }
  2966. case BuiltinFunctionType.AddressOf:
  2967. {
  2968. ProcessAddressOfInvocation(node);
  2969. break;
  2970. }
  2971. case BuiltinFunctionType.Eval:
  2972. {
  2973. ProcessEvalInvocation(node);
  2974. break;
  2975. }
  2976. default:
  2977. {
  2978. NotImplemented(node, "BuiltinFunction: " + function);
  2979. break;
  2980. }
  2981. }
  2982. }
  2983. bool ProcessSwitchInvocation(MethodInvocationExpression node)
  2984. {
  2985. if (BuiltinFunction.Switch != node.Target.Entity) return false;
  2986. BindSwitchLabelReferences(node);
  2987. if (CheckSwitchArguments(node)) return true;
  2988. Error(node, CompilerErrorFactory.InvalidSwitch(node.Target));
  2989. return true;
  2990. }
  2991. private static void BindSwitchLabelReferences(MethodInvocationExpression node)
  2992. {
  2993. for (int i = 1; i < node.Arguments.Count; ++i)
  2994. {
  2995. ReferenceExpression label = (ReferenceExpression)node.Arguments[i];
  2996. label.ExpressionType = Unknown.Default;
  2997. }
  2998. }
  2999. bool CheckSwitchArguments(MethodInvocationExpression node)
  3000. {
  3001. ExpressionCollection args = node.Arguments;
  3002. if (args.Count > 1)
  3003. {
  3004. Visit(args[0]);
  3005. if (TypeSystemServices.IsIntegerNumber(GetExpressionType(args[0])))
  3006. {
  3007. for (int i=1; i<args.Count; ++i)
  3008. {
  3009. if (NodeType.ReferenceExpression != args[i].NodeType)
  3010. {
  3011. return false;
  3012. }
  3013. }
  3014. return true;
  3015. }
  3016. }
  3017. return false;
  3018. }
  3019. void ProcessEvalInvocation(MethodInvocationExpression node)
  3020. {
  3021. if (node.Arguments.Count > 0)
  3022. {
  3023. int allButLast = node.Arguments.Count-1;
  3024. for (int i=0; i<allButLast; ++i)
  3025. {
  3026. AssertHasSideEffect(node.Arguments[i]);
  3027. }
  3028. BindExpressionType(node, GetConcreteExpressionType(node.Arguments.Last));
  3029. }
  3030. else
  3031. {
  3032. BindExpressionType(node, TypeSystemServices.VoidType);
  3033. }
  3034. }
  3035. void ProcessAddressOfInvocation(MethodInvocationExpression node)
  3036. {
  3037. if (node.Arguments.Count != 1)
  3038. {
  3039. Error(node, CompilerErrorFactory.MethodArgumentCount(node.Target, "__addressof__", 1));
  3040. }
  3041. else
  3042. {
  3043. Expression arg = node.Arguments[0];
  3044. EntityType type = GetEntity(arg).EntityType;
  3045. if (EntityType.Method != type)
  3046. {
  3047. var reference = arg as ReferenceExpression;
  3048. if (reference != null && type == EntityType.Ambiguous)
  3049. {
  3050. Error(node, CompilerErrorFactory.AmbiguousReference(arg, reference.Name, ((Ambiguous)arg.Entity).Entities));
  3051. }
  3052. else
  3053. {
  3054. Error(node, CompilerErrorFactory.MethodReferenceExpected(arg));
  3055. }
  3056. }
  3057. else
  3058. {
  3059. BindExpressionType(node, TypeSystemServices.IntPtrType);
  3060. }
  3061. }
  3062. }
  3063. void ProcessLenInvocation(MethodInvocationExpression node)
  3064. {
  3065. if ((node.Arguments.Count < 1) || (node.Arguments.Count > 2))
  3066. {
  3067. Error(node, CompilerErrorFactory.MethodArgumentCount(node.Target, "len", node.Arguments.Count));
  3068. return;
  3069. }
  3070. Expression resultingNode = null;
  3071. Expression target = node.Arguments[0];
  3072. IType type = GetExpressionType(target);
  3073. bool isArray = IsAssignableFrom(TypeSystemServices.ArrayType, type);
  3074. if ((!isArray) && (node.Arguments.Count != 1))
  3075. {
  3076. Error(node, CompilerErrorFactory.MethodArgumentCount(node.Target, "len", node.Arguments.Count));
  3077. }
  3078. if (TypeSystemServices.IsSystemObject(type))
  3079. {
  3080. resultingNode = CodeBuilder.CreateMethodInvocation(MethodCache.RuntimeServices_Len, target);
  3081. }
  3082. else if (TypeSystemServices.StringType == type)
  3083. {
  3084. resultingNode = CodeBuilder.CreateMethodInvocation(target, MethodCache.String_get_Length);
  3085. }
  3086. else if (isArray)
  3087. {
  3088. if (node.Arguments.Count == 1)
  3089. resultingNode = CodeBuilder.CreateMethodInvocation(target, MethodCache.Array_get_Length);
  3090. else
  3091. resultingNode = CodeBuilder.CreateMethodInvocation(target, MethodCache.Array_GetLength, node.Arguments[1]);
  3092. }
  3093. else if (IsAssignableFrom(TypeSystemServices.ICollectionType, type))
  3094. {
  3095. resultingNode = CodeBuilder.CreateMethodInvocation(target, MethodCache.ICollection_get_Count);
  3096. }
  3097. else if (GenericsServices.HasConstructedType(type, TypeSystemServices.ICollectionGenericType))
  3098. {
  3099. resultingNode = new MemberReferenceExpression(node.LexicalInfo, target, "Count");
  3100. Visit(resultingNode);
  3101. }
  3102. else
  3103. {
  3104. Error(CompilerErrorFactory.InvalidLen(target, type));
  3105. }
  3106. if (null != resultingNode)
  3107. {
  3108. node.ParentNode.Replace(node, resultingNode);
  3109. }
  3110. }
  3111. private void CheckItems(IType expectedElementType, ExpressionCollection items)
  3112. {
  3113. foreach (Expression element in items)
  3114. AssertTypeCompatibility(element, expectedElementType, GetExpressionType(element));
  3115. }
  3116. void ApplyBuiltinMethodTypeInference(MethodInvocationExpression expression, IMethod method)
  3117. {
  3118. var inferredType = _invocationTypeReferenceRules.Instance.ApplyTo(expression, method);
  3119. if (inferredType != null)
  3120. {
  3121. var parent = expression.ParentNode;
  3122. if (parent.NodeType != NodeType.ExpressionStatement)
  3123. parent.Replace(expression, CodeBuilder.CreateCast(inferredType, expression));
  3124. }
  3125. }
  3126. private EnvironmentProvision<InvocationTypeInferenceRules> _invocationTypeReferenceRules;
  3127. protected virtual IEntity ResolveAmbiguousMethodInvocation(MethodInvocationExpression node, IEntity entity)
  3128. {
  3129. Ambiguous ambiguous = entity as Ambiguous;
  3130. if (ambiguous == null)
  3131. return entity;
  3132. _context.TraceVerbose("{0}: resolving ambigous method invocation: {1}", node.LexicalInfo, entity);
  3133. IEntity resolved = ResolveCallableReference(node, ambiguous);
  3134. if (null != resolved)
  3135. return resolved;
  3136. // If resolution fails, try to resolve target as an extension method (but no more than once)
  3137. if (!ResolvedAsExtension(node) && TryToProcessAsExtensionInvocation(node))
  3138. {
  3139. return null;
  3140. }
  3141. return CantResolveAmbiguousMethodInvocation(node, ambiguous.Entities);
  3142. }
  3143. private IEntity ResolveCallableReference(MethodInvocationExpression node, Ambiguous entity)
  3144. {
  3145. var genericService = My<GenericsServices>.Instance;
  3146. var methods = entity.Entities
  3147. .OfType<IMethod>()
  3148. .Select(m => {
  3149. if (m.GenericInfo == null)
  3150. return m;
  3151. var inferrer = new GenericParameterInferrer(Context, m, node.Arguments);
  3152. inferrer.ResolveClosure += ProcessClosureInMethodInvocation;
  3153. if (!inferrer.Run())
  3154. return null;
  3155. var arguments = inferrer.GetInferredTypes();
  3156. if (arguments == null || !genericService.CheckGenericConstruction(m, arguments))
  3157. return null;
  3158. return m.GenericInfo.ConstructMethod(arguments);
  3159. }).Where(m => m != null).ToArray();
  3160. var resolved = CallableResolutionService.ResolveCallableReference(node.Arguments, methods);
  3161. if (null == resolved)
  3162. return null;
  3163. IMember member = (IMember)resolved;
  3164. if (NodeType.ReferenceExpression == node.Target.NodeType)
  3165. {
  3166. ResolveMemberInfo((ReferenceExpression)node.Target, member);
  3167. }
  3168. else
  3169. {
  3170. Bind(node.Target, member);
  3171. BindExpressionType(node.Target, member.Type);
  3172. }
  3173. return resolved;
  3174. }
  3175. private bool TryToProcessAsExtensionInvocation(MethodInvocationExpression node)
  3176. {
  3177. IEntity extension = ResolveExtension(node);
  3178. if (null == extension) return false;
  3179. node.Annotate(ResolvedAsExtensionAnnotation);
  3180. ProcessMethodInvocationExpression(node, extension);
  3181. return true;
  3182. }
  3183. private IEntity ResolveExtension(MethodInvocationExpression node)
  3184. {
  3185. ReferenceExpression targetReference = node.Target as ReferenceExpression;
  3186. if (targetReference == null) return null;
  3187. MemberReferenceExpression mre = targetReference as MemberReferenceExpression;
  3188. INamespace extensionNamespace = (mre != null) ? GetReferenceNamespace(mre) : CurrentType;
  3189. return NameResolutionService.ResolveExtension(extensionNamespace, targetReference.Name);
  3190. }
  3191. private static bool ResolvedAsExtension(MethodInvocationExpression node)
  3192. {
  3193. if (node.ContainsAnnotation(ResolvedAsExtensionAnnotation)
  3194. || node.Target.ContainsAnnotation(ResolvedAsExtensionAnnotation))
  3195. return true;
  3196. var genericReference = node.Target as GenericReferenceExpression;
  3197. return genericReference != null && genericReference.Target.ContainsAnnotation(ResolvedAsExtensionAnnotation);
  3198. }
  3199. protected virtual IEntity CantResolveAmbiguousMethodInvocation(MethodInvocationExpression node, IEntity[] entities)
  3200. {
  3201. EmitCallableResolutionError(node, entities, node.Arguments);
  3202. Error(node);
  3203. return null;
  3204. }
  3205. override public void OnMethodInvocationExpression(MethodInvocationExpression node)
  3206. {
  3207. if (null != node.ExpressionType)
  3208. {
  3209. _context.TraceVerbose("{0}: Method invocation already bound.", node.LexicalInfo);
  3210. return;
  3211. }
  3212. Visit(node.Target);
  3213. if (ProcessSwitchInvocation(node)) return;
  3214. if (ProcessMetaMethodInvocation(node, false)) return;
  3215. Visit(node.Arguments);
  3216. if (TypeSystemServices.IsError(node.Target)
  3217. || TypeSystemServices.IsErrorAny(node.Arguments))
  3218. {
  3219. Error(node);
  3220. return;
  3221. }
  3222. IEntity targetEntity = node.Target.Entity;
  3223. if (null == targetEntity)
  3224. {
  3225. ProcessGenericMethodInvocation(node);
  3226. return;
  3227. }
  3228. ProcessMethodInvocationExpression(node, targetEntity);
  3229. }
  3230. private bool ProcessMetaMethodInvocation(MethodInvocationExpression node, bool resolvedArgs)
  3231. {
  3232. var targetEntity = node.Target.Entity;
  3233. if (targetEntity == null) return false;
  3234. if (!IsOrContainMetaMethod(targetEntity)) return false;
  3235. var arguments = GetMetaMethodInvocationArguments(node);
  3236. var argumentTypes = MethodResolver.GetArgumentTypes(arguments);
  3237. var resolver = new MethodResolver(argumentTypes);
  3238. var method = resolver.ResolveMethod(EnumerateMetaMethods(targetEntity));
  3239. if (method == null) return false;
  3240. if (ShouldResolveArgsOf(method))
  3241. {
  3242. Visit(node.Arguments);
  3243. InvokeMetaMethod(node, method, GetMetaMethodInvocationArguments(node));
  3244. return true;
  3245. }
  3246. InvokeMetaMethod(node, method, arguments);
  3247. return true;
  3248. }
  3249. private static bool ShouldResolveArgsOf(CandidateMethod method)
  3250. {
  3251. return MetaAttributeOf(method).ResolveArgs;
  3252. }
  3253. private static MetaAttribute MetaAttributeOf(CandidateMethod method)
  3254. {
  3255. return (MetaAttribute) method.Method.GetCustomAttributes(typeof (MetaAttribute), false).Single();
  3256. }
  3257. private void InvokeMetaMethod(MethodInvocationExpression node, CandidateMethod method, object[] arguments)
  3258. {
  3259. var replacement = (Node) method.DynamicInvoke(null, arguments);
  3260. ReplaceMetaMethodInvocationSite(node, replacement);
  3261. }
  3262. private static object[] GetMetaMethodInvocationArguments(MethodInvocationExpression node)
  3263. {
  3264. if (node.NamedArguments.Count == 0)
  3265. return node.Arguments.ToArray();
  3266. var arguments = new List();
  3267. arguments.Add(node.NamedArguments.ToArray());
  3268. arguments.Extend(node.Arguments);
  3269. return arguments.ToArray();
  3270. }
  3271. private void ReplaceMetaMethodInvocationSite(MethodInvocationExpression node, Node replacement)
  3272. {
  3273. if (replacement == null || replacement is Statement)
  3274. {
  3275. if (node.ParentNode.NodeType != NodeType.ExpressionStatement)
  3276. NotImplemented(node, "Cant use an statement where an expression is expected.");
  3277. var statementParent = node.ParentNode.ParentNode;
  3278. statementParent.Replace(node.ParentNode, replacement);
  3279. if (replacement != null)
  3280. replacement = My<CodeReifier>.Instance.Reify((Statement)replacement);
  3281. }
  3282. else
  3283. {
  3284. node.ParentNode.Replace(node, replacement);
  3285. replacement = My<CodeReifier>.Instance.Reify((Expression) replacement);
  3286. }
  3287. Visit(replacement);
  3288. }
  3289. private IEnumerable<MethodInfo> EnumerateMetaMethods(IEntity entity)
  3290. {
  3291. if (entity.EntityType == EntityType.Method)
  3292. {
  3293. yield return GetMethodInfo(entity);
  3294. }
  3295. else
  3296. {
  3297. foreach (IEntity item in ((Ambiguous)entity).Entities)
  3298. {
  3299. yield return GetMethodInfo(item);
  3300. }
  3301. }
  3302. }
  3303. private static MethodInfo GetMethodInfo(IEntity entity)
  3304. {
  3305. return (MethodInfo)((ExternalMethod) entity).MethodInfo;
  3306. }
  3307. private bool IsOrContainMetaMethod(IEntity entity)
  3308. {
  3309. switch (entity.EntityType)
  3310. {
  3311. case EntityType.Ambiguous:
  3312. return ((Ambiguous) entity).Any(IsMetaMethod);
  3313. case EntityType.Method:
  3314. return IsMetaMethod(entity);
  3315. }
  3316. return false;
  3317. }
  3318. private static bool IsMetaMethod(IEntity entity)
  3319. {
  3320. ExternalMethod m = entity as ExternalMethod;
  3321. if (m == null) return false;
  3322. return m.IsMeta;
  3323. }
  3324. private void ProcessMethodInvocationExpression(MethodInvocationExpression node, IEntity targetEntity)
  3325. {
  3326. if (ResolvedAsExtension(node) || IsExtensionMethod(targetEntity))
  3327. {
  3328. PreNormalizeExtensionInvocation(node, targetEntity as IEntityWithParameters);
  3329. }
  3330. targetEntity = ResolveAmbiguousMethodInvocation(node, targetEntity);
  3331. if (targetEntity == null)
  3332. return;
  3333. switch (targetEntity.EntityType)
  3334. {
  3335. case EntityType.BuiltinFunction:
  3336. {
  3337. ProcessBuiltinInvocation(node, (BuiltinFunction)targetEntity);
  3338. break;
  3339. }
  3340. case EntityType.Event:
  3341. {
  3342. ProcessEventInvocation(node, (IEvent)targetEntity);
  3343. break;
  3344. }
  3345. case EntityType.Method:
  3346. {
  3347. ProcessMethodInvocation(node, (IMethod) targetEntity);
  3348. break;
  3349. }
  3350. case EntityType.Constructor:
  3351. {
  3352. ProcessConstructorInvocation(node, targetEntity);
  3353. break;
  3354. }
  3355. case EntityType.Type:
  3356. {
  3357. ProcessTypeInvocation(node);
  3358. break;
  3359. }
  3360. case EntityType.Error:
  3361. {
  3362. Error(node);
  3363. break;
  3364. }
  3365. default:
  3366. {
  3367. ProcessGenericMethodInvocation(node);
  3368. break;
  3369. }
  3370. }
  3371. }
  3372. private void ProcessConstructorInvocation(MethodInvocationExpression node, IEntity targetEntity)
  3373. {
  3374. NamedArgumentsNotAllowed(node);
  3375. InternalConstructor constructorInfo = targetEntity as InternalConstructor;
  3376. if (null == constructorInfo) return;
  3377. IType targetType = null;
  3378. if (NodeType.SuperLiteralExpression == node.Target.NodeType)
  3379. {
  3380. constructorInfo.HasSuperCall = true;
  3381. targetType = constructorInfo.DeclaringType.BaseType;
  3382. }
  3383. else if (node.Target.NodeType == NodeType.SelfLiteralExpression)
  3384. {
  3385. constructorInfo.HasSelfCall = true;
  3386. targetType = constructorInfo.DeclaringType;
  3387. }
  3388. IConstructor targetConstructorInfo = GetCorrectConstructor(node, targetType, node.Arguments);
  3389. if (null != targetConstructorInfo)
  3390. {
  3391. Bind(node.Target, targetConstructorInfo);
  3392. }
  3393. }
  3394. protected virtual bool ProcessMethodInvocationWithInvalidParameters(MethodInvocationExpression node, IMethod targetMethod)
  3395. {
  3396. return false;
  3397. }
  3398. protected virtual void ProcessMethodInvocation(MethodInvocationExpression node, IMethod method)
  3399. {
  3400. if (ResolvedAsExtension(node)) PostNormalizeExtensionInvocation(node, method);
  3401. var targetMethod = InferGenericMethodInvocation(node, method);
  3402. if (targetMethod == null) return;
  3403. if (!CheckParameters(targetMethod.CallableType, node.Arguments, false))
  3404. {
  3405. if (!ResolvedAsExtension(node) && TryToProcessAsExtensionInvocation(node)) return;
  3406. if (ProcessMethodInvocationWithInvalidParameters(node, targetMethod)) return;
  3407. AssertParameters(node, targetMethod, node.Arguments);
  3408. }
  3409. AssertTargetContext(node.Target, targetMethod);
  3410. NamedArgumentsNotAllowed(node);
  3411. EnsureRelatedNodeWasVisited(node.Target, targetMethod);
  3412. BindExpressionType(node, GetInferredType(targetMethod));
  3413. ApplyBuiltinMethodTypeInference(node, targetMethod);
  3414. }
  3415. private IMethod InferGenericMethodInvocation(MethodInvocationExpression node, IMethod targetMethod)
  3416. {
  3417. if (targetMethod.GenericInfo == null) return targetMethod;
  3418. GenericParameterInferrer inferrer = new GenericParameterInferrer(Context, targetMethod, node.Arguments);
  3419. inferrer.ResolveClosure += ProcessClosureInMethodInvocation;
  3420. if (!inferrer.Run())
  3421. {
  3422. CannotInferGenericMethodArguments(node, targetMethod);
  3423. return null;
  3424. }
  3425. IType[] inferredTypeArguments = inferrer.GetInferredTypes();
  3426. if (!_genericServices.Instance.CheckGenericConstruction(node, targetMethod, inferredTypeArguments, true))
  3427. {
  3428. Error(node);
  3429. return null;
  3430. }
  3431. IMethod constructedMethod = targetMethod.GenericInfo.ConstructMethod(inferredTypeArguments);
  3432. Bind(node.Target, constructedMethod);
  3433. BindExpressionType(node, GetInferredType(constructedMethod));
  3434. return constructedMethod;
  3435. }
  3436. private EnvironmentProvision<GenericsServices> _genericServices;
  3437. private void CannotInferGenericMethodArguments(Expression node, IMethod genericMethod)
  3438. {
  3439. Error(node, CompilerErrorFactory.CannotInferGenericMethodArguments(node, genericMethod));
  3440. }
  3441. private bool IsAccessible(IEntity member)
  3442. {
  3443. var accessible = member as IAccessibleMember;
  3444. if (accessible == null) return true;
  3445. return IsAccessible(accessible);
  3446. }
  3447. private bool IsAccessible(IAccessibleMember accessible)
  3448. {
  3449. return GetAccessibilityChecker().IsAccessible(accessible);
  3450. }
  3451. private IAccessibilityChecker GetAccessibilityChecker()
  3452. {
  3453. if (null == _currentMethod) return AccessibilityChecker.Global;
  3454. return new AccessibilityChecker(CurrentTypeDefinition);
  3455. }
  3456. private TypeDefinition CurrentTypeDefinition
  3457. {
  3458. get { return _currentMethod.Method.DeclaringType; }
  3459. }
  3460. private void NamedArgumentsNotAllowed(MethodInvocationExpression node)
  3461. {
  3462. if (node.NamedArguments.Count == 0) return;
  3463. Error(CompilerErrorFactory.NamedArgumentsNotAllowed(node.NamedArguments[0]));
  3464. }
  3465. private bool IsExtensionMethod(IEntity entity)
  3466. {
  3467. IExtensionEnabled extension = entity as IExtensionEnabled;
  3468. return null != extension && extension.IsExtension;
  3469. }
  3470. private void PostNormalizeExtensionInvocation(MethodInvocationExpression node, IMethod targetMethod)
  3471. {
  3472. node.Target = CodeBuilder.CreateMethodReference(node.Target.LexicalInfo, targetMethod);
  3473. }
  3474. private void PreNormalizeExtensionInvocation(MethodInvocationExpression node, IEntityWithParameters extension)
  3475. {
  3476. if (0 == node.Arguments.Count
  3477. || null == extension
  3478. || node.Arguments.Count < extension.GetParameters().Length)
  3479. {
  3480. node.Arguments.Insert(0, EnsureMemberReferenceForExtension(node).Target);
  3481. }
  3482. }
  3483. private MemberReferenceExpression EnsureMemberReferenceForExtension(MethodInvocationExpression node)
  3484. {
  3485. Expression target = node.Target;
  3486. GenericReferenceExpression gre = target as GenericReferenceExpression;
  3487. if (null != gre)
  3488. target = gre.Target;
  3489. MemberReferenceExpression memberRef = target as MemberReferenceExpression;
  3490. if (null != memberRef)
  3491. return memberRef;
  3492. node.Target = memberRef = CodeBuilder.MemberReferenceForEntity(
  3493. CreateSelfReference(),
  3494. GetEntity(node.Target));
  3495. return memberRef;
  3496. }
  3497. private SelfLiteralExpression CreateSelfReference()
  3498. {
  3499. return CodeBuilder.CreateSelfReference(CurrentType);
  3500. }
  3501. protected virtual bool IsDuckTyped(IMember entity)
  3502. {
  3503. return entity.IsDuckTyped;
  3504. }
  3505. private IType GetInferredType(IMethod entity)
  3506. {
  3507. return IsDuckTyped(entity)
  3508. ? this.TypeSystemServices.DuckType
  3509. : entity.ReturnType;
  3510. }
  3511. private IType GetInferredType(IMember entity)
  3512. {
  3513. Debug.Assert(EntityType.Method != entity.EntityType);
  3514. return IsDuckTyped(entity)
  3515. ? this.TypeSystemServices.DuckType
  3516. : entity.Type;
  3517. }
  3518. void ReplaceTypeInvocationByEval(IType type, MethodInvocationExpression node)
  3519. {
  3520. node.ParentNode.Replace(node, EvalForTypeInvocation(type, node));
  3521. }
  3522. private MethodInvocationExpression EvalForTypeInvocation(IType type, MethodInvocationExpression node)
  3523. {
  3524. MethodInvocationExpression eval = CodeBuilder.CreateEvalInvocation(node.LexicalInfo);
  3525. ReferenceExpression local = CreateTempLocal(node.Target.LexicalInfo, type);
  3526. eval.Arguments.Add(CodeBuilder.CreateAssignment(local.CloneNode(), node));
  3527. AddResolvedNamedArgumentsToEval(eval, node.NamedArguments, local);
  3528. node.NamedArguments.Clear();
  3529. eval.Arguments.Add(local);
  3530. BindExpressionType(eval, type);
  3531. return eval;
  3532. }
  3533. private void AddResolvedNamedArgumentsToEval(MethodInvocationExpression eval, ExpressionPairCollection namedArguments, ReferenceExpression instance)
  3534. {
  3535. foreach (ExpressionPair pair in namedArguments)
  3536. {
  3537. if (TypeSystemServices.IsError(pair.First)) continue;
  3538. AddResolvedNamedArgumentToEval(eval, pair, instance);
  3539. }
  3540. }
  3541. protected virtual void AddResolvedNamedArgumentToEval(MethodInvocationExpression eval, ExpressionPair pair, ReferenceExpression instance)
  3542. {
  3543. IEntity entity = GetEntity(pair.First);
  3544. switch (entity.EntityType)
  3545. {
  3546. case EntityType.Event:
  3547. {
  3548. IEvent member = (IEvent)entity;
  3549. eval.Arguments.Add(
  3550. CodeBuilder.CreateMethodInvocation(
  3551. pair.First.LexicalInfo,
  3552. instance.CloneNode(),
  3553. member.GetAddMethod(),
  3554. pair.Second));
  3555. break;
  3556. }
  3557. case EntityType.Field:
  3558. {
  3559. eval.Arguments.Add(
  3560. CodeBuilder.CreateAssignment(
  3561. pair.First.LexicalInfo,
  3562. CodeBuilder.CreateMemberReference(
  3563. instance.CloneNode(),
  3564. (IMember)entity),
  3565. pair.Second));
  3566. break;
  3567. }
  3568. case EntityType.Property:
  3569. {
  3570. IProperty property = (IProperty)entity;
  3571. IMethod setter = property.GetSetMethod();
  3572. if (null == setter)
  3573. {
  3574. Error(CompilerErrorFactory.PropertyIsReadOnly(pair.First, property));
  3575. }
  3576. else
  3577. {
  3578. //EnsureRelatedNodeWasVisited(pair.First, setter);
  3579. eval.Arguments.Add(
  3580. CodeBuilder.CreateAssignment(
  3581. pair.First.LexicalInfo,
  3582. CodeBuilder.CreateMemberReference(
  3583. instance.CloneNode(),
  3584. property),
  3585. pair.Second));
  3586. }
  3587. break;
  3588. }
  3589. }
  3590. }
  3591. void ProcessEventInvocation(MethodInvocationExpression node, IEvent ev)
  3592. {
  3593. NamedArgumentsNotAllowed(node);
  3594. if (!EnsureInternalEventInvocation(ev, node)) return;
  3595. IMethod method = ev.GetRaiseMethod();
  3596. if (AssertParameters(node, method, node.Arguments))
  3597. {
  3598. node.Target = CodeBuilder.CreateMemberReference(
  3599. ((MemberReferenceExpression)node.Target).Target,
  3600. method);
  3601. BindExpressionType(node, method.ReturnType);
  3602. }
  3603. }
  3604. public bool EnsureInternalEventInvocation(IEvent ev, Expression node)
  3605. {
  3606. if (ev.IsAbstract || ev.IsVirtual || ev.DeclaringType == CurrentType)
  3607. return true;
  3608. Error(CompilerErrorFactory.EventCanOnlyBeInvokedFromWithinDeclaringClass(node, ev));
  3609. return false;
  3610. }
  3611. void ProcessCallableTypeInvocation(MethodInvocationExpression node, ICallableType type)
  3612. {
  3613. NamedArgumentsNotAllowed(node);
  3614. if (node.Arguments.Count == 1)
  3615. {
  3616. AssertTypeCompatibility(node.Arguments[0], type, GetExpressionType(node.Arguments[0]));
  3617. node.ParentNode.Replace(
  3618. node,
  3619. CodeBuilder.CreateCast(
  3620. type,
  3621. node.Arguments[0]));
  3622. }
  3623. else
  3624. {
  3625. IConstructor ctor = GetCorrectConstructor(node, type, node.Arguments);
  3626. if (null != ctor)
  3627. {
  3628. BindConstructorInvocation(node, ctor);
  3629. }
  3630. else
  3631. {
  3632. Error(node);
  3633. }
  3634. }
  3635. }
  3636. void ProcessTypeInvocation(MethodInvocationExpression node)
  3637. {
  3638. var type = (IType)node.Target.Entity;
  3639. var callableType = type as ICallableType;
  3640. if (callableType != null)
  3641. {
  3642. ProcessCallableTypeInvocation(node, callableType);
  3643. return;
  3644. }
  3645. if (!AssertCanCreateInstance(node.Target, type))
  3646. {
  3647. Error(node);
  3648. return;
  3649. }
  3650. ResolveNamedArguments(type, node.NamedArguments);
  3651. if (type.IsValueType && node.Arguments.Count == 0)
  3652. {
  3653. ProcessValueTypeInstantiation(type, node);
  3654. return;
  3655. }
  3656. var ctor = GetCorrectConstructor(node, type, node.Arguments);
  3657. if (ctor != null)
  3658. {
  3659. BindConstructorInvocation(node, ctor);
  3660. if (node.NamedArguments.Count > 0)
  3661. ReplaceTypeInvocationByEval(type, node);
  3662. return;
  3663. }
  3664. Error(node);
  3665. }
  3666. void BindConstructorInvocation(MethodInvocationExpression node, IConstructor ctor)
  3667. {
  3668. // rebind the target now we know
  3669. // it is a constructor call
  3670. Bind(node.Target, ctor);
  3671. BindExpressionType(node.Target, ctor.Type);
  3672. BindExpressionType(node, ctor.DeclaringType);
  3673. }
  3674. private void ProcessValueTypeInstantiation(IType type, MethodInvocationExpression node)
  3675. {
  3676. var target = CodeBuilder.CreateReference(DeclareTempLocal(type));
  3677. Expression initializer = CodeBuilder.CreateDefaultInitializer(node.LexicalInfo, target, type);
  3678. MethodInvocationExpression eval = CodeBuilder.CreateEvalInvocation(node.LexicalInfo);
  3679. BindExpressionType(eval, type);
  3680. eval.Arguments.Add(initializer);
  3681. AddResolvedNamedArgumentsToEval(eval, node.NamedArguments, target.CloneNode());
  3682. eval.Arguments.Add(target.CloneNode());
  3683. node.ParentNode.Replace(node, eval);
  3684. }
  3685. void ProcessGenericMethodInvocation(MethodInvocationExpression node)
  3686. {
  3687. IType type = GetExpressionType(node.Target);
  3688. if (TypeSystemServices.IsCallable(type))
  3689. ProcessMethodInvocationOnCallableExpression(node);
  3690. else
  3691. Error(node, CompilerErrorFactory.TypeIsNotCallable(node.Target, type));
  3692. }
  3693. void ProcessMethodInvocationOnCallableExpression(MethodInvocationExpression node)
  3694. {
  3695. var type = GetConcreteExpressionType(node.Target);
  3696. var delegateType = type as ICallableType;
  3697. if (delegateType != null)
  3698. {
  3699. ProcessDelegateInvocation(node, delegateType);
  3700. return;
  3701. }
  3702. if (IsAssignableFrom(TypeSystemServices.ICallableType, type))
  3703. {
  3704. ProcessICallableInvocation(node);
  3705. return;
  3706. }
  3707. if (TypeSystemServices.TypeType == type)
  3708. {
  3709. ProcessSystemTypeInvocation(node);
  3710. return;
  3711. }
  3712. ProcessInvocationOnUnknownCallableExpression(node);
  3713. }
  3714. void ProcessDelegateInvocation(MethodInvocationExpression node, ICallableType delegateType)
  3715. {
  3716. if (!AssertParameters(node.Target, delegateType, delegateType, node.Arguments))
  3717. {
  3718. Error(node);
  3719. return;
  3720. }
  3721. var invoke = ResolveMethod(delegateType, "Invoke");
  3722. node.Target = CodeBuilder.CreateMemberReference(node.Target, invoke);
  3723. BindExpressionType(node, invoke.ReturnType);
  3724. }
  3725. void ProcessICallableInvocation(MethodInvocationExpression node)
  3726. {
  3727. node.Target = CodeBuilder.CreateMemberReference(node.Target, MethodCache.ICallable_Call);
  3728. var args = CodeBuilder.CreateObjectArray(node.Arguments);
  3729. node.Arguments.Clear();
  3730. node.Arguments.Add(args);
  3731. BindExpressionType(node, MethodCache.ICallable_Call.ReturnType);
  3732. }
  3733. private void ProcessSystemTypeInvocation(MethodInvocationExpression node)
  3734. {
  3735. var invocation = CreateInstanceInvocationFor(node);
  3736. if (invocation.NamedArguments.Count == 0)
  3737. {
  3738. node.ParentNode.Replace(node, invocation);
  3739. return;
  3740. }
  3741. ProcessNamedArgumentsForTypeInvocation(invocation);
  3742. node.ParentNode.Replace(node, EvalForTypeInvocation(TypeSystemServices.ObjectType, invocation));
  3743. }
  3744. private void ProcessNamedArgumentsForTypeInvocation(MethodInvocationExpression invocation)
  3745. {
  3746. foreach (ExpressionPair pair in invocation.NamedArguments)
  3747. {
  3748. if (!ProcessNamedArgument(pair)) continue;
  3749. NamedArgumentNotFound(TypeSystemServices.ObjectType, (ReferenceExpression)pair.First);
  3750. }
  3751. }
  3752. private MethodInvocationExpression CreateInstanceInvocationFor(MethodInvocationExpression node)
  3753. {
  3754. MethodInvocationExpression invocation = CodeBuilder.CreateMethodInvocation(MethodCache.Activator_CreateInstance, node.Target);
  3755. if (MethodCache.Activator_CreateInstance.AcceptVarArgs)
  3756. {
  3757. invocation.Arguments.AddRange(node.Arguments);
  3758. }
  3759. else
  3760. {
  3761. invocation.Arguments.Add(CodeBuilder.CreateObjectArray(node.Arguments));
  3762. }
  3763. invocation.NamedArguments = node.NamedArguments;
  3764. return invocation;
  3765. }
  3766. protected virtual void ProcessInvocationOnUnknownCallableExpression(MethodInvocationExpression node)
  3767. {
  3768. NotImplemented(node, "Method invocation on type '" + node.Target.ExpressionType + "'.");
  3769. }
  3770. bool AssertIdentifierName(Node node, string name)
  3771. {
  3772. if (TypeSystemServices.IsPrimitive(name))
  3773. {
  3774. Error(CompilerErrorFactory.CantRedefinePrimitive(node, name));
  3775. return false;
  3776. }
  3777. return true;
  3778. }
  3779. private bool CheckIsNotValueType(BinaryExpression node, Expression expression)
  3780. {
  3781. var type = GetExpressionType(expression);
  3782. if (!TypeSystemServices.IsReferenceType(type) && !TypeSystemServices.IsAnyType(type))
  3783. {
  3784. Error(CompilerErrorFactory.OperatorCantBeUsedWithValueType(
  3785. expression,
  3786. GetBinaryOperatorText(node.Operator),
  3787. type));
  3788. return false;
  3789. }
  3790. return true;
  3791. }
  3792. void BindAssignmentToSlice(BinaryExpression node)
  3793. {
  3794. var slice = (SlicingExpression)node.Left;
  3795. var expression = slice.Target;
  3796. if (!expression.Entity.IsAmbiguous() && IsArray(expression))
  3797. BindAssignmentToSliceArray(node);
  3798. else if (TypeSystemServices.IsDuckTyped(expression))
  3799. BindExpressionType(node, TypeSystemServices.DuckType);
  3800. else
  3801. BindAssignmentToSliceProperty(node);
  3802. }
  3803. private bool IsArray(Expression expression)
  3804. {
  3805. return GetExpressionType(expression).IsArray;
  3806. }
  3807. void BindAssignmentToSliceArray(BinaryExpression node)
  3808. {
  3809. var slice = (SlicingExpression)node.Left;
  3810. if (slice.IsComplexSlicing())
  3811. {
  3812. // FIXME: Check type compatibility
  3813. BindAssignmentToComplexSliceArray(node);
  3814. return;
  3815. }
  3816. var elementType = GetExpressionType(slice.Target).ElementType;
  3817. var expressionType = GetExpressionType(node.Right);
  3818. if (!AssertTypeCompatibility(node.Right, elementType, expressionType))
  3819. {
  3820. Error(node);
  3821. return;
  3822. }
  3823. node.ExpressionType = elementType;
  3824. }
  3825. void BindAssignmentToComplexSliceArray(BinaryExpression node)
  3826. {
  3827. var slice = (SlicingExpression)node.Left;
  3828. var ale = new ArrayLiteralExpression();
  3829. var collapse = new ArrayLiteralExpression();
  3830. var compute_end = new ArrayLiteralExpression();
  3831. for (int i = 0; i < slice.Indices.Count; i++)
  3832. {
  3833. ale.Items.Add(slice.Indices[i].Begin);
  3834. if (slice.Indices[i].End == null)
  3835. {
  3836. ale.Items.Add(new IntegerLiteralExpression(1 + (int)((IntegerLiteralExpression)slice.Indices[i].Begin).Value));
  3837. collapse.Items.Add(new BoolLiteralExpression(true));
  3838. compute_end.Items.Add(new BoolLiteralExpression(false));
  3839. }
  3840. else if (slice.Indices[i].End == OmittedExpression.Default)
  3841. {
  3842. ale.Items.Add(new IntegerLiteralExpression(0));
  3843. collapse.Items.Add(new BoolLiteralExpression(false));
  3844. compute_end.Items.Add(new BoolLiteralExpression(true));
  3845. }
  3846. else
  3847. {
  3848. ale.Items.Add(slice.Indices[i].End);
  3849. collapse.Items.Add(new BoolLiteralExpression(false));
  3850. compute_end.Items.Add(new BoolLiteralExpression(false));
  3851. }
  3852. }
  3853. var mie = CodeBuilder.CreateMethodInvocation(
  3854. MethodCache.RuntimeServices_SetMultiDimensionalRange1,
  3855. node.Right,
  3856. slice.Target,
  3857. ale);
  3858. mie.Arguments.Add(compute_end);
  3859. mie.Arguments.Add(collapse);
  3860. BindExpressionType(mie, TypeSystemServices.VoidType);
  3861. BindExpressionType(ale, TypeSystemServices.Map(typeof(int[])));
  3862. BindExpressionType(compute_end, TypeSystemServices.Map(typeof(bool[])));
  3863. BindExpressionType(collapse, TypeSystemServices.Map(typeof(bool[])));
  3864. node.ParentNode.Replace(node, mie);
  3865. }
  3866. void BindAssignmentToSliceProperty(BinaryExpression node)
  3867. {
  3868. var slice = (SlicingExpression)node.Left;
  3869. var lhs = GetEntity(node.Left);
  3870. if (IsError(lhs))
  3871. return;
  3872. var mie = new MethodInvocationExpression(node.Left.LexicalInfo);
  3873. foreach (var index in slice.Indices)
  3874. mie.Arguments.Add(index.Begin);
  3875. mie.Arguments.Add(node.Right);
  3876. IMethod setter = null;
  3877. var property = lhs as IProperty;
  3878. if (property != null)
  3879. {
  3880. var setMethod = property.GetSetMethod();
  3881. if (setMethod == null)
  3882. {
  3883. Error(node, CompilerErrorFactory.PropertyIsReadOnly(slice.Target, property));
  3884. return;
  3885. }
  3886. if (AssertParameters(node.Left, setMethod, mie.Arguments))
  3887. setter = setMethod;
  3888. }
  3889. else if (lhs.IsAmbiguous())
  3890. {
  3891. setter = (IMethod)GetCorrectCallableReference(node.Left, mie.Arguments, GetSetMethods(lhs));
  3892. if (setter == null)
  3893. {
  3894. Error(node.Left);
  3895. return;
  3896. }
  3897. }
  3898. if (null == setter)
  3899. Error(node, CompilerErrorFactory.LValueExpected(node.Left));
  3900. else
  3901. {
  3902. mie.Target = CodeBuilder.CreateMemberReference(
  3903. GetIndexedPropertySlicingTarget(slice),
  3904. setter);
  3905. BindExpressionType(mie, setter.ReturnType);
  3906. node.ParentNode.Replace(node, mie);
  3907. }
  3908. }
  3909. private IEntity[] GetSetMethods(IEntity candidates)
  3910. {
  3911. return GetSetMethods(((Ambiguous)candidates).Entities);
  3912. }
  3913. void BindAssignment(BinaryExpression node)
  3914. {
  3915. BindNullableOperation(node);
  3916. if (NodeType.SlicingExpression == node.Left.NodeType)
  3917. BindAssignmentToSlice(node);
  3918. else
  3919. ProcessAssignment(node);
  3920. }
  3921. virtual protected void ProcessAssignment(BinaryExpression node)
  3922. {
  3923. TryToResolveAmbiguousAssignment(node);
  3924. if (ValidateAssignment(node))
  3925. BindExpressionType(node, GetExpressionType(node.Right));
  3926. else
  3927. Error(node);
  3928. }
  3929. virtual protected bool ValidateAssignment(BinaryExpression node)
  3930. {
  3931. if (!AssertLValue(node.Left))
  3932. return false;
  3933. IType lhsType = GetExpressionType(node.Left);
  3934. IType rhsType = GetExpressionType(node.Right);
  3935. if (!AssertTypeCompatibility(node.Right, lhsType, rhsType))
  3936. return false;
  3937. CheckAssignmentToIndexedProperty(node.Left, node.Left.Entity);
  3938. return true;
  3939. }
  3940. virtual protected void TryToResolveAmbiguousAssignment(BinaryExpression node)
  3941. {
  3942. if (!node.Left.Entity.IsAmbiguous()) return;
  3943. var lvalue = node.Left;
  3944. var lhs = ResolveAmbiguousLValue(lvalue, (Ambiguous)node.Left.Entity, node.Right);
  3945. if (NodeType.ReferenceExpression == lvalue.NodeType)
  3946. {
  3947. IMember member = lhs as IMember;
  3948. if (null != member)
  3949. {
  3950. ResolveMemberInfo((ReferenceExpression)lvalue, member);
  3951. }
  3952. }
  3953. }
  3954. private void CheckAssignmentToIndexedProperty(Node node, IEntity lhs)
  3955. {
  3956. var property = lhs as IProperty;
  3957. if (property != null && property.IsIndexedProperty())
  3958. Error(CompilerErrorFactory.PropertyRequiresParameters(MemberAnchorFor(node), property));
  3959. }
  3960. bool CheckIsaArgument(Expression e)
  3961. {
  3962. if (TypeSystemServices.TypeType != GetExpressionType(e))
  3963. {
  3964. Error(CompilerErrorFactory.IsaArgument(e));
  3965. return false;
  3966. }
  3967. return true;
  3968. }
  3969. bool BindNullableOperation(BinaryExpression node)
  3970. {
  3971. if (!IsNullableOperation(node))
  3972. return false;
  3973. if (BinaryOperatorType.ReferenceEquality == node.Operator)
  3974. {
  3975. node.Operator = BinaryOperatorType.Equality;
  3976. return BindNullableComparison(node);
  3977. }
  3978. else if (BinaryOperatorType.ReferenceInequality == node.Operator)
  3979. {
  3980. node.Operator = BinaryOperatorType.Inequality;
  3981. return BindNullableComparison(node);
  3982. }
  3983. IType lhs = GetExpressionType(node.Left);
  3984. IType rhs = GetExpressionType(node.Right);
  3985. bool lhsIsNullable = TypeSystemServices.IsNullable(lhs);
  3986. bool rhsIsNullable = TypeSystemServices.IsNullable(rhs);
  3987. if (BinaryOperatorType.Assign == node.Operator)
  3988. {
  3989. if (lhsIsNullable)
  3990. {
  3991. if (rhsIsNullable)
  3992. return false;
  3993. BindNullableInitializer(node, node.Right, lhs);
  3994. return false;
  3995. }
  3996. }
  3997. if (lhsIsNullable)
  3998. {
  3999. MemberReferenceExpression mre = new MemberReferenceExpression(node.Left, "Value");
  4000. node.Replace(node.Left, mre);
  4001. Visit(mre);
  4002. mre.Annotate("nullableTarget", true);
  4003. }
  4004. if (rhsIsNullable)
  4005. {
  4006. MemberReferenceExpression mre = new MemberReferenceExpression(node.Right, "Value");
  4007. node.Replace(node.Right, mre);
  4008. Visit(mre);
  4009. mre.Annotate("nullableTarget", true);
  4010. }
  4011. return false;
  4012. }
  4013. bool BindNullableComparison(BinaryExpression node)
  4014. {
  4015. if (!IsNullableOperation(node))
  4016. return false;
  4017. if (IsNull(node.Left) || IsNull(node.Right))
  4018. {
  4019. Expression nullable = IsNull(node.Left) ? node.Right : node.Left;
  4020. Expression val = new MemberReferenceExpression(nullable, "HasValue");
  4021. node.Replace(node.Left, val);
  4022. Visit(val);
  4023. Expression nil = new BoolLiteralExpression(false);
  4024. node.Replace(node.Right, nil);
  4025. Visit(nil);
  4026. BindExpressionType(node, TypeSystemServices.BoolType);
  4027. return true;
  4028. }
  4029. BinaryExpression valueCheck = new BinaryExpression(
  4030. (node.Operator == BinaryOperatorType.Inequality)
  4031. ? BinaryOperatorType.BitwiseOr
  4032. : BinaryOperatorType.BitwiseAnd,
  4033. new BinaryExpression(
  4034. GetCorrespondingHasValueOperator(node.Operator),
  4035. CreateNullableHasValueOrTrueExpression(node.Left),
  4036. CreateNullableHasValueOrTrueExpression(node.Right)
  4037. ),
  4038. new BinaryExpression(
  4039. node.Operator,
  4040. CreateNullableGetValueOrDefaultExpression(node.Left),
  4041. CreateNullableGetValueOrDefaultExpression(node.Right)
  4042. )
  4043. );
  4044. node.ParentNode.Replace(node, valueCheck);
  4045. Visit(valueCheck);
  4046. return true;
  4047. }
  4048. private BinaryOperatorType GetCorrespondingHasValueOperator(BinaryOperatorType op)
  4049. {
  4050. if (BinaryOperatorType.Equality == op || BinaryOperatorType.Inequality == op)
  4051. return op;
  4052. //when there is at least one non-value operand then any other comparison
  4053. //than equality/inequality is undefined/false (as in C#)
  4054. return BinaryOperatorType.BitwiseAnd;
  4055. }
  4056. private IEnumerable<Expression> FindNullableExpressions(Expression exp)
  4057. {
  4058. if (exp.ContainsAnnotation("nullableTarget"))
  4059. {
  4060. yield return ((MemberReferenceExpression) exp).Target;
  4061. }
  4062. else
  4063. {
  4064. BinaryExpression bex = exp as BinaryExpression;
  4065. if (null != bex)
  4066. {
  4067. foreach (Expression inner in FindNullableExpressions(bex.Left))
  4068. yield return inner;
  4069. foreach (Expression inner in FindNullableExpressions(bex.Right))
  4070. yield return inner;
  4071. }
  4072. }
  4073. }
  4074. private Expression BuildNullableCoalescingConditional(Expression exp)
  4075. {
  4076. if (IsNull(exp)) return null;
  4077. IEnumerator<Expression> enumerator = FindNullableExpressions(exp).GetEnumerator();
  4078. Expression root = null;
  4079. BinaryExpression and = null;
  4080. Expression lookahead = null;
  4081. while (enumerator.MoveNext())
  4082. {
  4083. Expression cur = enumerator.Current;
  4084. lookahead = enumerator.MoveNext() ? enumerator.Current : null;
  4085. if (null != and)
  4086. {
  4087. and.Right = new BinaryExpression(
  4088. BinaryOperatorType.BitwiseAnd,
  4089. and.Right,
  4090. new BinaryExpression(
  4091. BinaryOperatorType.BitwiseAnd,
  4092. CreateNullableHasValueOrTrueExpression(cur),
  4093. CreateNullableHasValueOrTrueExpression(lookahead)
  4094. )
  4095. );
  4096. }
  4097. else
  4098. {
  4099. if (null == lookahead)
  4100. return CreateNullableHasValueOrTrueExpression(cur);
  4101. root = and = new BinaryExpression(
  4102. BinaryOperatorType.BitwiseAnd,
  4103. CreateNullableHasValueOrTrueExpression(cur),
  4104. CreateNullableHasValueOrTrueExpression(lookahead));
  4105. }
  4106. }
  4107. return root;
  4108. }
  4109. void BindNullableInitializer(Node node, Expression rhs, IType type)
  4110. {
  4111. var instantiation = CreateNullableInstantiation(rhs, type);
  4112. node.Replace(rhs, instantiation);
  4113. Visit(instantiation);
  4114. var coalescing = BuildNullableCoalescingConditional(rhs);
  4115. if (null != coalescing) //rhs contains at least one nullable
  4116. {
  4117. var cond = new ConditionalExpression
  4118. {
  4119. Condition = coalescing,
  4120. TrueValue = instantiation,
  4121. FalseValue = CreateNullableInstantiation(type)
  4122. };
  4123. node.Replace(instantiation, cond);
  4124. Visit(cond);
  4125. }
  4126. }
  4127. void BindNullableParameters(ExpressionCollection args, ICallableType target)
  4128. {
  4129. if (null == target)
  4130. return;
  4131. IParameter[] parameters = target.GetSignature().Parameters;
  4132. for (int i = 0; i < parameters.Length; ++i) {
  4133. if (!TypeSystemServices.IsNullable(parameters[i].Type))
  4134. continue;
  4135. if (TypeSystemServices.IsNullable(GetExpressionType(args[i])))
  4136. continue; //already nullable
  4137. args.Replace(args[i], CreateNullableInstantiation(args[i], parameters[i].Type));
  4138. Visit(args[i]);
  4139. }
  4140. }
  4141. private Expression CreateNullableInstantiation(IType type)
  4142. {
  4143. return CreateNullableInstantiation(null, type);
  4144. }
  4145. private Expression CreateNullableInstantiation(Expression val, IType type)
  4146. {
  4147. MethodInvocationExpression mie = new MethodInvocationExpression();
  4148. GenericReferenceExpression gre = new GenericReferenceExpression();
  4149. gre.Target = new MemberReferenceExpression(new ReferenceExpression("System"), "Nullable");
  4150. gre.GenericArguments.Add(TypeReference.Lift(Nullable.GetUnderlyingType(((ExternalType) type).ActualType)));
  4151. mie.Target = gre;
  4152. if (null != val && !IsNull(val))
  4153. mie.Arguments.Add(val);
  4154. return mie;
  4155. }
  4156. private Expression CreateNullableHasValueOrTrueExpression(Expression target)
  4157. {
  4158. if (null == target || !TypeSystemServices.IsNullable(GetExpressionType(target)))
  4159. return new BoolLiteralExpression(true);
  4160. return new MemberReferenceExpression(target, "HasValue");
  4161. }
  4162. private Expression CreateNullableGetValueOrDefaultExpression(Expression target)
  4163. {
  4164. if (null == target || !TypeSystemServices.IsNullable(GetExpressionType(target)))
  4165. return target;
  4166. MethodInvocationExpression mie = new MethodInvocationExpression();
  4167. mie.Target = new MemberReferenceExpression(target, "GetValueOrDefault");
  4168. return mie;
  4169. }
  4170. void BindTypeTest(BinaryExpression node)
  4171. {
  4172. if (CheckIsNotValueType(node, node.Left) && CheckIsaArgument(node.Right))
  4173. BindExpressionType(node, TypeSystemServices.BoolType);
  4174. else
  4175. Error(node);
  4176. }
  4177. void BindReferenceEquality(BinaryExpression node)
  4178. {
  4179. BindReferenceEquality(node, false);
  4180. }
  4181. void BindReferenceEquality(BinaryExpression node, bool inequality)
  4182. {
  4183. if (BindNullableOperation(node))
  4184. {
  4185. return;
  4186. }
  4187. //BOO-1174: accept `booleanExpression is true|false`
  4188. BoolLiteralExpression isBool = node.Right as BoolLiteralExpression;
  4189. if (null != isBool)
  4190. {
  4191. if (GetExpressionType(node.Left) == TypeSystemServices.BoolType)
  4192. {
  4193. Node replacement = (isBool.Value ^ inequality)
  4194. ? node.Left
  4195. : new UnaryExpression(UnaryOperatorType.LogicalNot, node.Left);
  4196. node.ParentNode.Replace(node, replacement);
  4197. Visit(replacement);
  4198. return;
  4199. }
  4200. }
  4201. if (CheckIsNotValueType(node, node.Left) &&
  4202. CheckIsNotValueType(node, node.Right))
  4203. {
  4204. BindExpressionType(node, TypeSystemServices.BoolType);
  4205. }
  4206. else
  4207. {
  4208. Error(node);
  4209. }
  4210. }
  4211. void BindInPlaceArithmeticOperator(BinaryExpression node)
  4212. {
  4213. if (IsArraySlicing(node.Left))
  4214. {
  4215. BindInPlaceArithmeticOperatorOnArraySlicing(node);
  4216. return;
  4217. }
  4218. Node parent = node.ParentNode;
  4219. Expression target = node.Left;
  4220. if (null != target.Entity && EntityType.Property == target.Entity.EntityType)
  4221. {
  4222. // if target is a property force a rebinding
  4223. target.ExpressionType = null;
  4224. }
  4225. BinaryExpression assign = ExpandInPlaceBinaryExpression(node);
  4226. parent.Replace(node, assign);
  4227. Visit(assign);
  4228. }
  4229. protected BinaryExpression ExpandInPlaceBinaryExpression(BinaryExpression node)
  4230. {
  4231. BinaryExpression assign = new BinaryExpression(node.LexicalInfo);
  4232. assign.Operator = BinaryOperatorType.Assign;
  4233. assign.Left = node.Left.CloneNode();
  4234. assign.Right = node;
  4235. node.Operator = GetRelatedBinaryOperatorForInPlaceOperator(node.Operator);
  4236. return assign;
  4237. }
  4238. private void BindInPlaceArithmeticOperatorOnArraySlicing(BinaryExpression node)
  4239. {
  4240. Node parent = node.ParentNode;
  4241. Expression expansion = CreateSideEffectAwareSlicingOperation(
  4242. node.LexicalInfo,
  4243. GetRelatedBinaryOperatorForInPlaceOperator(node.Operator),
  4244. (SlicingExpression) node.Left,
  4245. node.Right,
  4246. null);
  4247. parent.Replace(node, expansion);
  4248. }
  4249. BinaryOperatorType GetRelatedBinaryOperatorForInPlaceOperator(BinaryOperatorType op)
  4250. {
  4251. switch (op)
  4252. {
  4253. case BinaryOperatorType.InPlaceAddition:
  4254. return BinaryOperatorType.Addition;
  4255. case BinaryOperatorType.InPlaceSubtraction:
  4256. return BinaryOperatorType.Subtraction;
  4257. case BinaryOperatorType.InPlaceMultiply:
  4258. return BinaryOperatorType.Multiply;
  4259. case BinaryOperatorType.InPlaceDivision:
  4260. return BinaryOperatorType.Division;
  4261. case BinaryOperatorType.InPlaceModulus:
  4262. return BinaryOperatorType.Modulus;
  4263. case BinaryOperatorType.InPlaceBitwiseAnd:
  4264. return BinaryOperatorType.BitwiseAnd;
  4265. case BinaryOperatorType.InPlaceBitwiseOr:
  4266. return BinaryOperatorType.BitwiseOr;
  4267. case BinaryOperatorType.InPlaceExclusiveOr:
  4268. return BinaryOperatorType.ExclusiveOr;
  4269. case BinaryOperatorType.InPlaceShiftLeft:
  4270. return BinaryOperatorType.ShiftLeft;
  4271. case BinaryOperatorType.InPlaceShiftRight:
  4272. return BinaryOperatorType.ShiftRight;
  4273. }
  4274. throw new ArgumentException("op");
  4275. }
  4276. void BindArrayAddition(BinaryExpression node)
  4277. {
  4278. IArrayType lhs = (IArrayType)GetExpressionType(node.Left);
  4279. IArrayType rhs = (IArrayType)GetExpressionType(node.Right);
  4280. if (lhs.ElementType == rhs.ElementType)
  4281. {
  4282. node.ParentNode.Replace(
  4283. node,
  4284. CodeBuilder.CreateCast(
  4285. lhs,
  4286. CodeBuilder.CreateMethodInvocation(
  4287. MethodCache.RuntimeServices_AddArrays,
  4288. CodeBuilder.CreateTypeofExpression(lhs.ElementType),
  4289. node.Left,
  4290. node.Right)));
  4291. }
  4292. else
  4293. {
  4294. InvalidOperatorForTypes(node);
  4295. }
  4296. }
  4297. void BindArithmeticOperator(BinaryExpression node)
  4298. {
  4299. BindNullableOperation(node);
  4300. IType left = GetExpressionType(node.Left);
  4301. IType right = GetExpressionType(node.Right);
  4302. if (TypeSystemServices.IsPrimitiveNumber(left) && TypeSystemServices.IsPrimitiveNumber(right))
  4303. {
  4304. BindExpressionType(node, TypeSystemServices.GetPromotedNumberType(left, right));
  4305. }
  4306. else if (left.IsPointer && !BindPointerArithmeticOperator(node, left, right))
  4307. {
  4308. InvalidOperatorForTypes(node);
  4309. }
  4310. else if (!ResolveOperator(node))
  4311. {
  4312. InvalidOperatorForTypes(node);
  4313. }
  4314. }
  4315. bool BindPointerArithmeticOperator(BinaryExpression node, IType left, IType right)
  4316. {
  4317. if (!left.IsPointer || !TypeSystemServices.IsPrimitiveNumber(right))
  4318. return false;
  4319. switch (node.Operator)
  4320. {
  4321. case BinaryOperatorType.Addition:
  4322. case BinaryOperatorType.Subtraction:
  4323. if (node.ContainsAnnotation("pointerSizeNormalized"))
  4324. return true;
  4325. BindExpressionType(node, left);
  4326. int size = TypeSystemServices.SizeOf(left);
  4327. if (size == 1)
  4328. return true; //no need for normalization
  4329. //normalize RHS wrt size of pointer
  4330. IntegerLiteralExpression literal = node.Right as IntegerLiteralExpression;
  4331. Expression normalizedRhs = (null != literal)
  4332. ? (Expression)
  4333. new IntegerLiteralExpression(literal.Value * size)
  4334. : (Expression)
  4335. new BinaryExpression(BinaryOperatorType.Multiply,
  4336. node.Right,
  4337. new IntegerLiteralExpression(size));
  4338. node.Replace(node.Right, normalizedRhs);
  4339. Visit(node.Right);
  4340. node.Annotate("pointerSizeNormalized", size);
  4341. return true;
  4342. }
  4343. return false;
  4344. }
  4345. static string GetBinaryOperatorText(BinaryOperatorType op)
  4346. {
  4347. return BooPrinterVisitor.GetBinaryOperatorText(op);
  4348. }
  4349. static string GetUnaryOperatorText(UnaryOperatorType op)
  4350. {
  4351. return BooPrinterVisitor.GetUnaryOperatorText(op);
  4352. }
  4353. IEntity ResolveName(Node node, string name)
  4354. {
  4355. var entity = NameResolutionService.Resolve(name);
  4356. CheckNameResolution(node, name, entity);
  4357. return entity;
  4358. }
  4359. IEntity TryToResolveName(string name)
  4360. {
  4361. return NameResolutionService.Resolve(name);
  4362. }
  4363. protected void ClearResolutionCacheFor(string name)
  4364. {
  4365. NameResolutionService.ClearResolutionCacheFor(name);
  4366. }
  4367. protected bool CheckNameResolution(Node node, string name, IEntity resolvedEntity)
  4368. {
  4369. if (null == resolvedEntity)
  4370. {
  4371. EmitUnknownIdentifierError(node, name);
  4372. return false;
  4373. }
  4374. return true;
  4375. }
  4376. protected void EmitUnknownIdentifierError(Node node, string name)
  4377. {
  4378. Error(CompilerErrorFactory.UnknownIdentifier(node, name));
  4379. }
  4380. private static bool IsPublicEvent(IEntity tag)
  4381. {
  4382. return (EntityType.Event == tag.EntityType) && ((IMember)tag).IsPublic;
  4383. }
  4384. private static bool IsVisibleFieldPropertyOrEvent(IEntity entity)
  4385. {
  4386. switch (entity.EntityType)
  4387. {
  4388. case EntityType.Field:
  4389. var field = (IField)entity;
  4390. return !TypeSystemServices.IsReadOnlyField(field) && IsVisible(field);
  4391. case EntityType.Event:
  4392. var @event = (IEvent)entity;
  4393. return IsVisible(@event.GetAddMethod());
  4394. case EntityType.Property:
  4395. var property = (IProperty)entity;
  4396. return IsVisible(property);
  4397. }
  4398. return false;
  4399. }
  4400. private static bool IsVisible(IAccessibleMember member)
  4401. {
  4402. // TODO: should it just be IsAccessible(member) here?
  4403. return member.IsPublic || member.IsInternal;
  4404. }
  4405. private IMember ResolveVisibleFieldPropertyOrEvent(Expression sourceNode, IType type, string name)
  4406. {
  4407. IEntity candidate = ResolveFieldPropertyEvent(type, name);
  4408. if (null == candidate) return null;
  4409. if (IsVisibleFieldPropertyOrEvent(candidate)) return (IMember)candidate;
  4410. if (!candidate.IsAmbiguous()) return null;
  4411. IList<IEntity> found = ((Ambiguous)candidate).Select(IsVisibleFieldPropertyOrEvent);
  4412. if (found.Count == 0) return null;
  4413. if (found.Count == 1) return (IMember)found[0];
  4414. Error(sourceNode, CompilerErrorFactory.AmbiguousReference(sourceNode, name, found));
  4415. return null;
  4416. }
  4417. protected IEntity ResolveFieldPropertyEvent(IType type, string name)
  4418. {
  4419. return NameResolutionService.Resolve(type, name, EntityType.Property|EntityType.Event|EntityType.Field);
  4420. }
  4421. void ResolveNamedArguments(IType type, ExpressionPairCollection arguments)
  4422. {
  4423. foreach (ExpressionPair arg in arguments)
  4424. {
  4425. if (!ProcessNamedArgument(arg)) continue;
  4426. ResolveNamedArgument(type, (ReferenceExpression)arg.First, arg.Second);
  4427. }
  4428. }
  4429. private bool ProcessNamedArgument(ExpressionPair arg)
  4430. {
  4431. Visit(arg.Second);
  4432. if (NodeType.ReferenceExpression != arg.First.NodeType)
  4433. {
  4434. Error(arg.First, CompilerErrorFactory.NamedParameterMustBeIdentifier(arg));
  4435. return false;
  4436. }
  4437. return true;
  4438. }
  4439. void ResolveNamedArgument(IType type, ReferenceExpression name, Expression value)
  4440. {
  4441. IMember member = ResolveVisibleFieldPropertyOrEvent(name, type, name.Name);
  4442. if (null == member)
  4443. {
  4444. NamedArgumentNotFound(type, name);
  4445. return;
  4446. }
  4447. EnsureRelatedNodeWasVisited(name, member);
  4448. Bind(name, member);
  4449. IType memberType = member.Type;
  4450. if (member.EntityType == EntityType.Event)
  4451. {
  4452. AssertDelegateArgument(value, member, GetExpressionType(value));
  4453. }
  4454. else
  4455. {
  4456. AssertTypeCompatibility(value, memberType, GetExpressionType(value));
  4457. }
  4458. }
  4459. protected virtual void NamedArgumentNotFound(IType type, ReferenceExpression name)
  4460. {
  4461. Error(name, CompilerErrorFactory.NotAPublicFieldOrProperty(name, name.Name, type));
  4462. }
  4463. bool AssertTypeCompatibility(Node sourceNode, IType expectedType, IType actualType)
  4464. {
  4465. return TypeChecker.AssertTypeCompatibility(sourceNode, expectedType, actualType);
  4466. }
  4467. bool CanBeReachedFrom(Node anchor, IType expectedType, IType actualType)
  4468. {
  4469. return TypeChecker.CanBeReachedFrom(anchor, expectedType, actualType);
  4470. }
  4471. private TypeChecker TypeChecker
  4472. {
  4473. get { return _typeChecker.Instance; }
  4474. }
  4475. private EnvironmentProvision<TypeChecker> _typeChecker;
  4476. bool AssertDelegateArgument(Node sourceNode, ITypedEntity delegateMember, ITypedEntity argumentInfo)
  4477. {
  4478. if (!IsAssignableFrom(delegateMember.Type, argumentInfo.Type))
  4479. {
  4480. Error(CompilerErrorFactory.EventArgumentMustBeAMethod(sourceNode, delegateMember));
  4481. return false;
  4482. }
  4483. return true;
  4484. }
  4485. bool CheckParameterTypesStrictly(IMethod method, ExpressionCollection args)
  4486. {
  4487. IParameter[] parameters = method.GetParameters();
  4488. for (int i=0; i<args.Count; ++i)
  4489. {
  4490. IType expressionType = GetExpressionType(args[i]);
  4491. IType parameterType = parameters[i].Type;
  4492. if (!IsAssignableFrom(parameterType, expressionType) &&
  4493. !(TypeSystemServices.IsNumber(expressionType) && TypeSystemServices.IsNumber(parameterType))
  4494. && TypeSystemServices.FindImplicitConversionOperator(expressionType,parameterType) == null)
  4495. {
  4496. return false;
  4497. }
  4498. }
  4499. return true;
  4500. }
  4501. bool AssertParameterTypes(ICallableType method, ExpressionCollection args, int count, bool reportErrors)
  4502. {
  4503. IParameter[] parameters = method.GetSignature().Parameters;
  4504. for (int i=0; i<count; ++i)
  4505. {
  4506. IParameter param = parameters[i];
  4507. IType parameterType = param.Type;
  4508. IType argumentType = GetExpressionType(args[i]);
  4509. if (param.IsByRef)
  4510. {
  4511. if (!(args[i] is ReferenceExpression
  4512. || args[i] is SlicingExpression
  4513. || (args[i] is SelfLiteralExpression && argumentType.IsValueType)))
  4514. {
  4515. if (reportErrors)
  4516. Error(CompilerErrorFactory.RefArgTakesLValue(args[i]));
  4517. return false;
  4518. }
  4519. if (!CallableResolutionService.IsValidByRefArg(param, parameterType, argumentType, args[i]))
  4520. {
  4521. return false;
  4522. }
  4523. }
  4524. else
  4525. {
  4526. if (!CanBeReachedFrom(args[i], parameterType, argumentType))
  4527. return false;
  4528. }
  4529. }
  4530. return true;
  4531. }
  4532. bool AssertParameters(Node sourceNode, IMethod method, ExpressionCollection args)
  4533. {
  4534. return AssertParameters(sourceNode, method, method.CallableType, args);
  4535. }
  4536. bool AcceptVarArgs(ICallableType method)
  4537. {
  4538. return method.GetSignature().AcceptVarArgs;
  4539. }
  4540. bool AssertParameters(Node sourceNode, IEntity sourceEntity, ICallableType method, ExpressionCollection args)
  4541. {
  4542. if (CheckParameters(method, args, true))
  4543. return true;
  4544. if (IsLikelyMacroExtensionMethodInvocation(sourceEntity))
  4545. Error(CompilerErrorFactory.MacroExpansionError(sourceNode));
  4546. else
  4547. Error(CompilerErrorFactory.MethodSignature(sourceNode, sourceEntity, GetSignature(args)));
  4548. return false;
  4549. }
  4550. bool IsLikelyMacroExtensionMethodInvocation(IEntity entity)
  4551. {
  4552. IMethod extension = entity as IMethod;
  4553. return extension != null
  4554. && extension.IsExtension
  4555. && TypeSystemServices.IsMacro(extension.ReturnType)
  4556. && extension.GetParameters().Length == 2
  4557. && TypeSystemServices.IsMacro(extension.GetParameters()[0].Type);
  4558. }
  4559. protected virtual bool CheckParameters(ICallableType method, ExpressionCollection args, bool reportErrors)
  4560. {
  4561. BindNullableParameters(args, method);
  4562. return AcceptVarArgs(method)
  4563. ? CheckVarArgsParameters(method, args)
  4564. : CheckExactArgsParameters(method, args, reportErrors);
  4565. }
  4566. protected bool CheckVarArgsParameters(ICallableType method, ExpressionCollection args)
  4567. {
  4568. return CallableResolutionService.IsValidVargsInvocation(method.GetSignature().Parameters, args);
  4569. }
  4570. protected bool CheckExactArgsParameters(ICallableType method, ExpressionCollection args, bool reportErrors)
  4571. {
  4572. if (method.GetSignature().Parameters.Length != args.Count) return false;
  4573. return AssertParameterTypes(method, args, args.Count, reportErrors);
  4574. }
  4575. bool IsRuntimeIterator(IType type)
  4576. {
  4577. return TypeSystemServices.IsSystemObject(type)
  4578. || IsTextReader(type);
  4579. }
  4580. bool IsTextReader(IType type)
  4581. {
  4582. return IsAssignableFrom(typeof(TextReader), type);
  4583. }
  4584. bool AssertTargetContext(Expression targetContext, IMember member)
  4585. {
  4586. if (member.IsStatic) return true;
  4587. if (NodeType.MemberReferenceExpression != targetContext.NodeType) return true;
  4588. Expression targetReference = ((MemberReferenceExpression)targetContext).Target;
  4589. IEntity entity = targetReference.Entity;
  4590. if ((null != entity && EntityType.Type == entity.EntityType)
  4591. || (NodeType.SelfLiteralExpression == targetReference.NodeType
  4592. && _currentMethod.IsStatic))
  4593. {
  4594. Error(CompilerErrorFactory.InstanceRequired(targetContext, member));
  4595. return false;
  4596. }
  4597. return true;
  4598. }
  4599. static bool IsAssignableFrom(IType expectedType, IType actualType)
  4600. {
  4601. return TypeCompatibilityRules.IsAssignableFrom(expectedType, actualType);
  4602. }
  4603. bool IsAssignableFrom(Type expectedType, IType actualType)
  4604. {
  4605. return IsAssignableFrom(TypeSystemServices.Map(expectedType), actualType);
  4606. }
  4607. bool IsPrimitiveNumber(Expression expression)
  4608. {
  4609. return TypeSystemServices.IsPrimitiveNumber(GetExpressionType(expression));
  4610. }
  4611. IConstructor GetCorrectConstructor(Node sourceNode, IType type, ExpressionCollection arguments)
  4612. {
  4613. var constructors = type.GetConstructors().ToArray();
  4614. if (constructors.Length > 0)
  4615. return (IConstructor)GetCorrectCallableReference(sourceNode, arguments, constructors);
  4616. if (!IsError(type))
  4617. {
  4618. if (type is IGenericParameter)
  4619. Error(CompilerErrorFactory.CannotCreateAnInstanceOfGenericParameterWithoutDefaultConstructorConstraint(sourceNode, type));
  4620. else
  4621. Error(CompilerErrorFactory.NoApropriateConstructorFound(sourceNode, type, GetSignature(arguments)));
  4622. }
  4623. return null;
  4624. }
  4625. IEntity GetCorrectCallableReference(Node sourceNode, ExpressionCollection args, IEntity[] candidates)
  4626. {
  4627. // BOO-844: Ensure all candidates were visited (to make property setters have correct signature)
  4628. EnsureRelatedNodesWereVisited(sourceNode, candidates);
  4629. var found = CallableResolutionService.ResolveCallableReference(args, candidates);
  4630. if (found == null)
  4631. EmitCallableResolutionError(sourceNode, candidates, args);
  4632. else
  4633. BindNullableParameters(args, ((IMethodBase) found).CallableType);
  4634. return found;
  4635. }
  4636. private void EnsureRelatedNodesWereVisited(Node sourceNode, IEntity[] candidates)
  4637. {
  4638. foreach (var candidate in candidates)
  4639. EnsureRelatedNodeWasVisited(sourceNode, candidate);
  4640. }
  4641. private void EmitCallableResolutionError(Node sourceNode, IEntity[] candidates, ExpressionCollection args)
  4642. {
  4643. //if this is call without arguments and ambiguous contains generic method without arguments
  4644. //than emit BCE0164 for readability
  4645. var genericMethod = candidates.OfType<IMethod>().FirstOrDefault(m => m.GenericInfo != null && m.GetParameters().Length == 0);
  4646. if (args.Count == 0 && genericMethod != null)
  4647. {
  4648. Error(CompilerErrorFactory.CannotInferGenericMethodArguments(sourceNode, genericMethod));
  4649. return;
  4650. }
  4651. if (CallableResolutionService.ValidCandidates.Count > 1)
  4652. {
  4653. Error(CompilerErrorFactory.AmbiguousReference(sourceNode, candidates[0].Name, CallableResolutionService.ValidCandidates.Select(c => (IEntity)c.Method)));
  4654. return;
  4655. }
  4656. var candidate = candidates[0];
  4657. var constructor = candidate as IConstructor;
  4658. if (constructor != null)
  4659. {
  4660. Error(CompilerErrorFactory.NoApropriateConstructorFound(sourceNode, constructor.DeclaringType, GetSignature(args)));
  4661. }
  4662. else
  4663. {
  4664. Error(CompilerErrorFactory.NoApropriateOverloadFound(sourceNode, GetSignature(args), candidate.FullName));
  4665. }
  4666. }
  4667. override protected void EnsureRelatedNodeWasVisited(Node sourceNode, IEntity entity)
  4668. {
  4669. IInternalEntity internalInfo = GetConstructedInternalEntity(entity);
  4670. if (null == internalInfo)
  4671. {
  4672. ITypedEntity typedEntity = entity as ITypedEntity;
  4673. if (null == typedEntity) return;
  4674. internalInfo = typedEntity.Type as IInternalEntity;
  4675. if (null == internalInfo) return;
  4676. }
  4677. Node node = internalInfo.Node;
  4678. switch (node.NodeType)
  4679. {
  4680. case NodeType.Property:
  4681. case NodeType.Field:
  4682. {
  4683. IMember memberEntity = (IMember)entity;
  4684. if (EntityType.Property == entity.EntityType
  4685. || TypeSystemServices.IsUnknown(memberEntity.Type))
  4686. {
  4687. EnsureMemberWasVisited((TypeMember)node);
  4688. AssertTypeIsKnown(sourceNode, memberEntity, memberEntity.Type);
  4689. }
  4690. break;
  4691. }
  4692. case NodeType.Method:
  4693. {
  4694. IMethod methodEntity = (IMethod)entity;
  4695. if (TypeSystemServices.IsUnknown(methodEntity.ReturnType))
  4696. {
  4697. // try to preprocess the method to resolve its return type
  4698. Method method = (Method)node;
  4699. PreProcessMethod(method);
  4700. if (TypeSystemServices.IsUnknown(methodEntity.ReturnType))
  4701. {
  4702. // still unknown?
  4703. EnsureMemberWasVisited(method);
  4704. AssertTypeIsKnown(sourceNode, methodEntity, methodEntity.ReturnType);
  4705. }
  4706. }
  4707. break;
  4708. }
  4709. case NodeType.ClassDefinition:
  4710. case NodeType.StructDefinition:
  4711. case NodeType.InterfaceDefinition:
  4712. {
  4713. EnsureMemberWasVisited((TypeDefinition)node);
  4714. break;
  4715. }
  4716. }
  4717. }
  4718. private void EnsureMemberWasVisited(TypeMember node)
  4719. {
  4720. if (WasVisited(node))
  4721. return;
  4722. _context.TraceVerbose("Info {0} needs resolving.", node.Entity.Name);
  4723. VisitMemberPreservingContext(node);
  4724. }
  4725. protected virtual void VisitMemberPreservingContext(TypeMember node)
  4726. {
  4727. INamespace saved = NameResolutionService.CurrentNamespace;
  4728. try
  4729. {
  4730. NameResolutionService.EnterNamespace((INamespace)node.DeclaringType.Entity);
  4731. Visit(node);
  4732. }
  4733. finally
  4734. {
  4735. NameResolutionService.EnterNamespace(saved);
  4736. }
  4737. }
  4738. private void AssertTypeIsKnown(Node sourceNode, IEntity sourceEntity, IType type)
  4739. {
  4740. if (TypeSystemServices.IsUnknown(type))
  4741. {
  4742. Error(
  4743. CompilerErrorFactory.UnresolvedDependency(
  4744. sourceNode,
  4745. GetEntity(CurrentMember),
  4746. sourceEntity));
  4747. }
  4748. }
  4749. bool ResolveOperator(UnaryExpression node)
  4750. {
  4751. MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo);
  4752. mie.Arguments.Add(node.Operand.CloneNode());
  4753. string operatorName = AstUtil.GetMethodNameForOperator(node.Operator);
  4754. IType operand = GetExpressionType(node.Operand);
  4755. if (ResolveOperator(node, operand, operatorName, mie))
  4756. {
  4757. return true;
  4758. }
  4759. return ResolveOperator(node, TypeSystemServices.RuntimeServicesType, operatorName, mie);
  4760. }
  4761. bool ResolveOperator(BinaryExpression node)
  4762. {
  4763. MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo);
  4764. mie.Arguments.Add(node.Left.CloneNode());
  4765. mie.Arguments.Add(node.Right.CloneNode());
  4766. string operatorName = AstUtil.GetMethodNameForOperator(node.Operator);
  4767. IType lhs = GetExpressionType(node.Left);
  4768. if (ResolveOperator(node, lhs, operatorName, mie))
  4769. {
  4770. return true;
  4771. }
  4772. IType rhs = GetExpressionType(node.Right);
  4773. if (ResolveOperator(node, rhs, operatorName, mie))
  4774. {
  4775. return true;
  4776. }
  4777. //pointer arithmetic
  4778. if (lhs.IsPointer && TypeSystemServices.IsIntegerNumber(rhs))
  4779. {
  4780. switch (node.Operator)
  4781. {
  4782. case BinaryOperatorType.Addition:
  4783. case BinaryOperatorType.Subtraction:
  4784. return true;
  4785. }
  4786. }
  4787. return ResolveRuntimeOperator(node, operatorName, mie);
  4788. }
  4789. protected virtual bool ResolveRuntimeOperator(BinaryExpression node, string operatorName, MethodInvocationExpression mie)
  4790. {
  4791. return ResolveOperator(node, TypeSystemServices.RuntimeServicesType, operatorName, mie);
  4792. }
  4793. IMethod ResolveAmbiguousOperator(IEntity[] entities, ExpressionCollection args)
  4794. {
  4795. foreach (IEntity entity in entities)
  4796. {
  4797. IMethod method = entity as IMethod;
  4798. if (null != method)
  4799. {
  4800. if (HasOperatorSignature(method, args))
  4801. {
  4802. return method;
  4803. }
  4804. }
  4805. }
  4806. return null;
  4807. }
  4808. bool HasOperatorSignature(IMethod method, ExpressionCollection args)
  4809. {
  4810. return method.IsStatic &&
  4811. (args.Count == method.GetParameters().Length) &&
  4812. CheckParameterTypesStrictly(method, args);
  4813. }
  4814. IMethod FindOperator(IType type, string operatorName, ExpressionCollection args)
  4815. {
  4816. IEntity entity = NameResolutionService.Resolve(type, operatorName, EntityType.Method);
  4817. if (entity != null)
  4818. {
  4819. IMethod method = ResolveOperatorEntity(entity, args);
  4820. if (null != method) return method;
  4821. }
  4822. entity = NameResolutionService.ResolveExtension(type, operatorName);
  4823. if (entity != null)
  4824. return ResolveOperatorEntity(entity, args);
  4825. return null;
  4826. }
  4827. private IMethod ResolveOperatorEntity(IEntity op, ExpressionCollection args)
  4828. {
  4829. if (op.IsAmbiguous())
  4830. return ResolveAmbiguousOperator(((Ambiguous)op).Entities, args);
  4831. if (EntityType.Method == op.EntityType)
  4832. {
  4833. IMethod candidate = (IMethod)op;
  4834. if (HasOperatorSignature(candidate, args))
  4835. return candidate;
  4836. }
  4837. return null;
  4838. }
  4839. bool ResolveOperator(Expression node, IType type, string operatorName, MethodInvocationExpression mie)
  4840. {
  4841. IMethod entity = FindOperator(type, operatorName, mie.Arguments);
  4842. if (null == entity)
  4843. return false;
  4844. EnsureRelatedNodeWasVisited(node, entity);
  4845. mie.Target = new ReferenceExpression(entity.FullName);
  4846. IMethod operatorMethod = entity;
  4847. BindExpressionType(mie, operatorMethod.ReturnType);
  4848. BindExpressionType(mie.Target, operatorMethod.Type);
  4849. Bind(mie.Target, entity);
  4850. node.ParentNode.Replace(node, mie);
  4851. return true;
  4852. }
  4853. ReferenceExpression CreateTempLocal(LexicalInfo li, IType type)
  4854. {
  4855. InternalLocal local = DeclareTempLocal(type);
  4856. ReferenceExpression reference = new ReferenceExpression(li, local.Name);
  4857. reference.Entity = local;
  4858. reference.ExpressionType = type;
  4859. return reference;
  4860. }
  4861. protected InternalLocal DeclareTempLocal(IType localType)
  4862. {
  4863. return CodeBuilder.DeclareTempLocal(CurrentMethod, localType);
  4864. }
  4865. IEntity DeclareLocal(Node sourceNode, string name, IType localType)
  4866. {
  4867. return DeclareLocal(sourceNode, name, localType, false);
  4868. }
  4869. virtual protected IEntity DeclareLocal(Node sourceNode, string name, IType localType, bool privateScope)
  4870. {
  4871. ClearResolutionCacheFor(name);
  4872. var local = new Local(name, privateScope);
  4873. local.LexicalInfo = sourceNode.LexicalInfo;
  4874. local.IsSynthetic = sourceNode.IsSynthetic;
  4875. var entity = new InternalLocal(local, localType);
  4876. local.Entity = entity;
  4877. CurrentMethod.Locals.Add(local);
  4878. return entity;
  4879. }
  4880. protected IType CurrentType
  4881. {
  4882. get
  4883. {
  4884. return _currentMethod.DeclaringType;
  4885. }
  4886. }
  4887. void PushMember(TypeMember member)
  4888. {
  4889. _memberStack.Push(member);
  4890. }
  4891. TypeMember CurrentMember
  4892. {
  4893. get
  4894. {
  4895. return (TypeMember)_memberStack.Peek();
  4896. }
  4897. }
  4898. void PopMember()
  4899. {
  4900. _memberStack.Pop();
  4901. }
  4902. void PushMethodInfo(InternalMethod entity)
  4903. {
  4904. _methodStack.Push(_currentMethod);
  4905. _currentMethod = entity;
  4906. }
  4907. void PopMethodInfo()
  4908. {
  4909. _currentMethod = _methodStack.Pop();
  4910. }
  4911. void AssertHasSideEffect(Expression expression)
  4912. {
  4913. if (!HasSideEffect(expression) && !TypeSystemServices.IsError(expression))
  4914. {
  4915. Error(CompilerErrorFactory.ExpressionMustBeExecutedForItsSideEffects(expression));
  4916. }
  4917. }
  4918. protected virtual bool HasSideEffect(Expression node)
  4919. {
  4920. return
  4921. node.NodeType == NodeType.MethodInvocationExpression ||
  4922. AstUtil.IsAssignment(node) ||
  4923. AstUtil.IsIncDec(node);
  4924. }
  4925. bool AssertCanCreateInstance(Node sourceNode, IType type)
  4926. {
  4927. if (type.IsInterface)
  4928. {
  4929. Error(CompilerErrorFactory.CantCreateInstanceOfInterface(sourceNode, type));
  4930. return false;
  4931. }
  4932. if (type.IsEnum)
  4933. {
  4934. Error(CompilerErrorFactory.CantCreateInstanceOfEnum(sourceNode, type));
  4935. return false;
  4936. }
  4937. if (type.IsAbstract)
  4938. {
  4939. Error(CompilerErrorFactory.CantCreateInstanceOfAbstractType(sourceNode, type));
  4940. return false;
  4941. }
  4942. if (!(type is GenericConstructedType)
  4943. && ((type.GenericInfo != null && type.GenericInfo.GenericParameters.Length > 0)
  4944. || (type.ConstructedInfo != null && !type.ConstructedInfo.FullyConstructed)))
  4945. {
  4946. Error(CompilerErrorFactory.GenericTypesMustBeConstructedToBeInstantiated(sourceNode));
  4947. return false;
  4948. }
  4949. return true;
  4950. }
  4951. protected bool AssertDeclarationName(Declaration d)
  4952. {
  4953. if (AssertIdentifierName(d, d.Name))
  4954. return AssertUniqueLocal(d);
  4955. return false;
  4956. }
  4957. protected bool AssertUniqueLocal(Declaration d)
  4958. {
  4959. if (null == _currentMethod.ResolveLocal(d.Name) &&
  4960. null == _currentMethod.ResolveParameter(d.Name))
  4961. return true;
  4962. Error(CompilerErrorFactory.LocalAlreadyExists(d, d.Name));
  4963. return false;
  4964. }
  4965. void GetDeclarationType(IType defaultDeclarationType, Declaration d)
  4966. {
  4967. if (null != d.Type)
  4968. {
  4969. Visit(d.Type);
  4970. AssertTypeCompatibility(d, GetType(d.Type), defaultDeclarationType);
  4971. }
  4972. else
  4973. {
  4974. d.Type = CodeBuilder.CreateTypeReference(defaultDeclarationType);
  4975. }
  4976. }
  4977. void DeclareLocal(Declaration d, bool privateScope)
  4978. {
  4979. AssertIdentifierName(d, d.Name);
  4980. var local = DeclareLocal(d, d.Name, GetType(d.Type), privateScope);
  4981. d.Entity = local;
  4982. var internalLocal = local as InternalLocal;
  4983. if (internalLocal != null)
  4984. internalLocal.OriginalDeclaration = d;
  4985. }
  4986. protected IType GetEnumeratorItemType(IType iteratorType)
  4987. {
  4988. return TypeSystemServices.GetEnumeratorItemType(iteratorType);
  4989. }
  4990. protected void ProcessDeclarationsForIterator(DeclarationCollection declarations, IType iteratorType)
  4991. {
  4992. var defaultDeclType = GetEnumeratorItemType(iteratorType);
  4993. if (declarations.Count > 1)
  4994. // will enumerate (unpack) each item
  4995. defaultDeclType = GetEnumeratorItemType(defaultDeclType);
  4996. foreach (var d in declarations)
  4997. ProcessDeclarationForIterator(d, defaultDeclType);
  4998. }
  4999. protected virtual Local LocalToReuseFor(Declaration d)
  5000. {
  5001. return d.Type != null ? null : LocalByName(d.Name);
  5002. }
  5003. protected Local LocalByName(string name)
  5004. {
  5005. return AstUtil.GetLocalByName(CurrentMethod, name);
  5006. }
  5007. protected void ProcessDeclarationForIterator(Declaration d, IType defaultDeclType)
  5008. {
  5009. var local = LocalToReuseFor(d);
  5010. if (local != null)
  5011. {
  5012. var localType = ((InternalLocal)GetEntity(local)).Type;
  5013. AssertTypeCompatibility(d, localType, defaultDeclType);
  5014. d.Type = CodeBuilder.CreateTypeReference(localType);
  5015. d.Entity = local.Entity;
  5016. return;
  5017. }
  5018. GetDeclarationType(defaultDeclType, d);
  5019. DeclareLocal(d, true);
  5020. }
  5021. private bool AssertLValue(Expression node)
  5022. {
  5023. if (IsError(GetExpressionType(node)))
  5024. return false;
  5025. var entity = node.Entity;
  5026. if (null != entity)
  5027. return AssertLValue(node, entity);
  5028. if (IsArraySlicing(node))
  5029. return true;
  5030. LValueExpected(node);
  5031. return false;
  5032. }
  5033. private void LValueExpected(Node node)
  5034. {
  5035. var entity = node.Entity;
  5036. if (null != entity && IsError(entity))
  5037. return;
  5038. Error(CompilerErrorFactory.LValueExpected(node));
  5039. }
  5040. protected virtual bool AssertLValue(Node node, IEntity entity)
  5041. {
  5042. if (null != entity)
  5043. {
  5044. switch (entity.EntityType)
  5045. {
  5046. case EntityType.Error:
  5047. return false;
  5048. case EntityType.Parameter:
  5049. case EntityType.Local:
  5050. case EntityType.Event: //for Event=null case (other => EventIsNotAnExpression)
  5051. return true;
  5052. case EntityType.Property:
  5053. {
  5054. var property = ((IProperty)entity);
  5055. if (property.GetSetMethod() == null)
  5056. {
  5057. Error(CompilerErrorFactory.PropertyIsReadOnly(MemberAnchorFor(node), property));
  5058. return false;
  5059. }
  5060. return true;
  5061. }
  5062. case EntityType.Field:
  5063. {
  5064. IField fld = (IField)entity;
  5065. if (TypeSystemServices.IsReadOnlyField(fld))
  5066. {
  5067. if (EntityType.Constructor == _currentMethod.EntityType
  5068. && _currentMethod.DeclaringType == fld.DeclaringType
  5069. && fld.IsStatic == _currentMethod.IsStatic)
  5070. {
  5071. InternalField ifld = entity as InternalField;
  5072. if (null != ifld && ifld.IsStatic)
  5073. ifld.StaticValue = null; //downgrade 'literal' to 'init-only'
  5074. }
  5075. else
  5076. {
  5077. Error(CompilerErrorFactory.FieldIsReadonly(MemberAnchorFor(node), entity.FullName));
  5078. return false;
  5079. }
  5080. }
  5081. return true;
  5082. }
  5083. }
  5084. }
  5085. LValueExpected(node);
  5086. return false;
  5087. }
  5088. public static bool IsArraySlicing(Node node)
  5089. {
  5090. if (node.NodeType != NodeType.SlicingExpression) return false;
  5091. var type = ((SlicingExpression)node).Target.ExpressionType;
  5092. return type != null && type.IsArray;
  5093. }
  5094. private static bool IsStandaloneReference(Node node)
  5095. {
  5096. return AstUtil.IsStandaloneReference(node);
  5097. }
  5098. string GetSignature(IEnumerable args)
  5099. {
  5100. var sb = new StringBuilder("(");
  5101. foreach (Expression arg in args)
  5102. {
  5103. if (sb.Length > 1)
  5104. sb.Append(", ");
  5105. if (AstUtil.IsExplodeExpression(arg))
  5106. sb.Append('*');
  5107. sb.Append(GetExpressionType(arg).DisplayName());
  5108. }
  5109. sb.Append(")");
  5110. return sb.ToString();
  5111. }
  5112. void InvalidOperatorForType(UnaryExpression node)
  5113. {
  5114. Error(node, CompilerErrorFactory.InvalidOperatorForType(node,
  5115. GetUnaryOperatorText(node.Operator),
  5116. GetExpressionType(node.Operand)));
  5117. }
  5118. void InvalidOperatorForTypes(BinaryExpression node)
  5119. {
  5120. Error(node, CompilerErrorFactory.InvalidOperatorForTypes(node,
  5121. GetBinaryOperatorText(node.Operator),
  5122. GetExpressionType(node.Left),
  5123. GetExpressionType(node.Right)));
  5124. }
  5125. void TraceReturnType(Method method, IMethod tag)
  5126. {
  5127. _context.TraceInfo("{0}: return type for method {1} bound to {2}", method.LexicalInfo, method.Name, tag.ReturnType);
  5128. }
  5129. public bool OptimizeNullComparisons
  5130. {
  5131. get { return _optimizeNullComparisons; }
  5132. set { _optimizeNullComparisons = value; }
  5133. }
  5134. public TypeMember Reify(TypeMember member)
  5135. {
  5136. Visit(member);
  5137. var field = member as Field;
  5138. if (field != null)
  5139. FlushFieldInitializers((ClassDefinition) field.DeclaringType);
  5140. return member;
  5141. }
  5142. }
  5143. }