BOO-999
[boo.git] / src / Boo.Lang.Compiler / Steps / ProcessMethodBodies.cs
blob1f9b46dd661b66a5f4981c84df960c1eacb915c9
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.
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
29 using System;
30 using System.Collections;
31 using System.Diagnostics;
32 using System.IO;
33 using System.Reflection;
34 using System.Text;
35 using Boo.Lang.Compiler.Ast;
36 using Boo.Lang.Compiler.Ast.Visitors;
37 using Boo.Lang.Compiler.TypeSystem;
38 using Boo.Lang.Runtime;
39 using Attribute = Boo.Lang.Compiler.Ast.Attribute;
40 using Module=Boo.Lang.Compiler.Ast.Module;
42 namespace Boo.Lang.Compiler.Steps
44 /// <summary>
45 /// AST semantic evaluation.
46 /// </summary>
47 public class ProcessMethodBodies : AbstractNamespaceSensitiveVisitorCompilerStep
49 static readonly ExpressionCollection EmptyExpressionCollection = new ExpressionCollection();
51 static readonly object OptionalReturnStatementAnnotation = new object();
53 protected Stack _methodStack;
55 protected Stack _memberStack;
56 // for accurate error reporting during type inference
58 protected Module _currentModule;
60 protected InternalMethod _currentMethod;
62 IMethod Array_EnumerableConstructor;
64 IMethod Array_TypedEnumerableConstructor;
66 IMethod Array_TypedCollectionConstructor;
68 IMethod Array_TypedConstructor2;
70 IMethod MultiDimensionalArray_TypedConstructor;
72 protected CallableResolutionService _callableResolution;
74 protected bool _optimizeNullComparisons = true;
76 public ProcessMethodBodies()
80 override public void Run()
82 NameResolutionService.Reset();
84 _currentModule = null;
85 _currentMethod = null;
86 _methodStack = new Stack();
87 _memberStack = new Stack();
89 _callableResolution = new CallableResolutionService();
90 _callableResolution.Initialize(_context);
92 InitializeMemberCache();
94 Visit(CompileUnit);
97 protected IMethod ResolveMethod(IType type, string name)
99 return NameResolutionService.ResolveMethod(type, name);
102 protected IProperty ResolveProperty(IType type, string name)
104 return NameResolutionService.ResolveProperty(type, name);
107 virtual protected void InitializeMemberCache()
109 Array_EnumerableConstructor = TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.IEnumerable }));
110 Array_TypedEnumerableConstructor = TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.IEnumerable }));
111 Array_TypedCollectionConstructor= TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.ICollection }));
112 Array_TypedConstructor2 = TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.Int }));
113 MultiDimensionalArray_TypedConstructor = TypeSystemServices.Map(Types.Builtins.GetMethod("matrix", new Type[] { Types.Type, typeof(int[]) }));
116 override public void Dispose()
118 base.Dispose();
120 if (null != _callableResolution)
122 _callableResolution.Dispose();
123 _callableResolution = null;
126 _currentModule = null;
127 _currentMethod = null;
128 _methodStack = null;
129 _memberStack = null;
131 _RuntimeServices_Len = null;
132 _RuntimeServices_Mid = null;
133 _RuntimeServices_NormalizeStringIndex = null;
134 _RuntimeServices_AddArrays = null;
135 _RuntimeServices_GetRange1 = null;
136 _RuntimeServices_GetRange2 = null;
137 _RuntimeServices_GetMultiDimensionalRange1 = null;
138 _RuntimeServices_SetMultiDimensionalRange1 = null;
139 _RuntimeServices_GetEnumerable = null;
140 _RuntimeServices_EqualityOperator = null;
141 _Array_get_Length = null;
142 _Array_GetLength = null;
143 _String_get_Length = null;
144 _String_Substring_Int = null;
145 _ICollection_get_Count = null;
146 _List_GetRange1 = null;
147 _List_GetRange2 = null;
148 _ICallable_Call = null;
149 _Activator_CreateInstance = null;
150 _Exception_StringConstructor = null;
151 _TextReaderEnumerator_lines = null;
154 override public void OnModule(Module module)
156 if (WasVisited(module)) return;
157 MarkVisited(module);
158 _currentModule = module;
160 EnterNamespace((INamespace)TypeSystemServices.GetEntity(module));
162 Visit(module.Members);
163 Visit(module.AssemblyAttributes);
165 LeaveNamespace();
168 override public void OnInterfaceDefinition(InterfaceDefinition node)
170 if (WasVisited(node)) return;
171 MarkVisited(node);
173 VisitTypeDefinition(node);
176 private void VisitBaseTypes(TypeDefinition node)
178 foreach (TypeReference typeRef in node.BaseTypes)
180 EnsureRelatedNodeWasVisited(typeRef, typeRef.Entity);
184 private void VisitTypeDefinition(TypeDefinition node)
186 INamespace ns = (INamespace)GetEntity(node);
187 EnterNamespace(ns);
188 VisitBaseTypes(node);
189 Visit(node.Attributes);
190 Visit(node.Members);
191 LeaveNamespace();
194 override public void OnClassDefinition(ClassDefinition node)
196 if (WasVisited(node)) return;
197 MarkVisited(node);
199 VisitTypeDefinition(node);
200 ProcessFieldInitializers(node);
203 void ProcessFieldInitializers(ClassDefinition node)
205 foreach (TypeMember member in node.Members)
207 if (NodeType.Field == member.NodeType)
209 ProcessFieldInitializer((Field) member);
214 override public void OnAttribute(Attribute node)
216 IType tag = node.Entity as IType;
217 if (null != tag && !TypeSystemServices.IsError(tag))
219 Visit(node.Arguments);
220 ResolveNamedArguments(tag, node.NamedArguments);
222 IConstructor constructor = GetCorrectConstructor(node, tag, node.Arguments);
223 if (null != constructor)
225 Bind(node, constructor);
230 override public void OnProperty(Property node)
232 if (WasVisited(node))
234 return;
236 MarkVisited(node);
238 Method setter = node.Setter;
239 Method getter = node.Getter;
241 Visit(node.Attributes);
242 Visit(node.Type);
243 Visit(node.Parameters);
245 ResolvePropertyOverride(node);
247 if (null != getter)
249 if (null != node.Type)
251 getter.ReturnType = node.Type.CloneNode();
253 getter.Parameters.ExtendWithClones(node.Parameters);
255 Visit(getter);
258 IType typeInfo = null;
259 if (null != node.Type)
261 typeInfo = GetType(node.Type);
263 else
265 if (null != getter)
267 typeInfo = GetType(node.Getter.ReturnType);
268 if (typeInfo == TypeSystemServices.VoidType)
270 typeInfo = TypeSystemServices.ObjectType;
271 node.Getter.ReturnType = CodeBuilder.CreateTypeReference(getter.LexicalInfo, typeInfo);
274 else
276 typeInfo = TypeSystemServices.ObjectType;
278 node.Type = CodeBuilder.CreateTypeReference(node.LexicalInfo, typeInfo);
281 if (null != setter)
283 ParameterDeclaration parameter = new ParameterDeclaration();
284 parameter.Type = CodeBuilder.CreateTypeReference(typeInfo);
285 parameter.Name = "value";
286 parameter.Entity = new InternalParameter(parameter, node.Parameters.Count+CodeBuilder.GetFirstParameterIndex(setter));
287 setter.Parameters.ExtendWithClones(node.Parameters);
288 setter.Parameters.Add(parameter);
289 setter.Name = "set_" + node.Name;
290 Visit(setter);
294 override public void OnField(Field node)
296 if (WasVisited(node)) return;
297 MarkVisited(node);
299 InternalField entity = (InternalField)GetEntity(node);
301 Visit(node.Attributes);
302 Visit(node.Type);
304 if (null != node.Initializer)
306 IType type = (null != node.Type) ? GetType(node.Type) : null;
307 if (null != type && TypeSystemServices.IsNullable(type))
309 BindNullableInitializer(node, node.Initializer, type);
311 if (entity.DeclaringType.IsValueType && !node.IsStatic)
313 Error(
314 CompilerErrorFactory.ValueTypeFieldsCannotHaveInitializers(
315 node.Initializer));
319 PushMember(node);
320 PreProcessFieldInitializer(node);
322 finally
324 PopMember();
327 else
329 if (null == node.Type)
331 node.Type = CreateTypeReference(node.LexicalInfo, TypeSystemServices.ObjectType);
334 CheckFieldType(node.Type);
337 bool IsValidLiteralInitializer(Expression e)
339 switch (e.NodeType)
341 case NodeType.BoolLiteralExpression:
342 case NodeType.IntegerLiteralExpression:
343 case NodeType.DoubleLiteralExpression:
344 case NodeType.NullLiteralExpression:
345 case NodeType.StringLiteralExpression:
347 return true;
350 return false;
353 void ProcessLiteralField(Field node)
355 Visit(node.Initializer);
356 ProcessFieldInitializerType(node, node.Initializer.ExpressionType);
357 ((InternalField)node.Entity).StaticValue = node.Initializer;
358 node.Initializer = null;
361 void ProcessFieldInitializerType(Field node, IType initializerType)
363 if (null == node.Type)
365 node.Type = CreateTypeReference(node.LexicalInfo, MapNullToObject(initializerType));
367 else
369 AssertTypeCompatibility(node.Initializer, GetType(node.Type), initializerType);
373 private TypeReference CreateTypeReference(LexicalInfo info, IType type)
375 TypeReference reference = CodeBuilder.CreateTypeReference(type);
376 reference.LexicalInfo = info;
377 return reference;
380 private void PreProcessFieldInitializer(Field node)
382 Expression initializer = node.Initializer;
383 if (node.IsFinal && node.IsStatic)
385 if (IsValidLiteralInitializer(initializer))
387 ProcessLiteralField(node);
388 return;
392 Method method = GetFieldsInitializerMethod(node);
393 InternalMethod entity = (InternalMethod)method.Entity;
395 ReferenceExpression temp = new ReferenceExpression("___temp_initializer");
396 BinaryExpression assignment = new BinaryExpression(
397 node.LexicalInfo,
398 BinaryOperatorType.Assign,
399 temp,
400 initializer);
402 ProcessNodeInMethodContext(entity, entity, assignment);
403 method.Locals.RemoveByEntity(temp.Entity);
405 IType initializerType = GetExpressionType(assignment.Right);
406 ProcessFieldInitializerType(node, initializerType);
407 node.Initializer = assignment.Right;
410 void ProcessFieldInitializer(Field node)
412 Expression initializer = node.Initializer;
413 if (null == initializer) return;
415 Method method = GetFieldsInitializerMethod(node);
416 method.Body.Add(
417 CodeBuilder.CreateAssignment(
418 initializer.LexicalInfo,
419 CodeBuilder.CreateReference(node),
420 initializer));
421 node.Initializer = null;
424 Method CreateInitializerMethod(TypeDefinition type, string name, TypeMemberModifiers modifiers)
426 Method method = new Method(name);
427 method.Modifiers |= modifiers;
428 method.ReturnType = CodeBuilder.CreateTypeReference(TypeSystemServices.VoidType);
430 InternalMethod entity = new InternalMethod(TypeSystemServices, method);
431 method.Entity = entity;
432 type.Members.Add(method);
433 MarkVisited(method);
434 return method;
437 Method GetFieldsInitializerMethod(Field node)
439 TypeDefinition type = node.DeclaringType;
440 string methodName = node.IsStatic ? "$static_initializer$" : "$initializer$";
441 Method method = (Method)type[methodName];
442 if (null == method)
444 if (node.IsStatic)
446 if (null == FindStaticConstructor(type))
448 // when the class doesnt have a static constructor
449 // yet, create one and use it as the static
450 // field initializer method
451 method = CreateStaticConstructor(type);
453 else
455 method = CreateInitializerMethod(type, methodName, TypeMemberModifiers.Static);
456 AddInitializerToStaticConstructor(type, (InternalMethod)method.Entity);
459 else
461 method = CreateInitializerMethod(type, methodName, TypeMemberModifiers.None);
462 AddInitializerToInstanceConstructors(type, (InternalMethod)method.Entity);
465 type[methodName] = method;
467 return method;
470 void AddInitializerToStaticConstructor(TypeDefinition type, InternalMethod initializer)
472 GetStaticConstructor(type).Body.Insert(0,
473 CodeBuilder.CreateMethodInvocation(initializer));
476 void AddInitializerToInstanceConstructors(TypeDefinition type, InternalMethod initializer)
478 foreach (TypeMember node in type.Members)
480 if (NodeType.Constructor == node.NodeType && !node.IsStatic)
482 Constructor constructor = (Constructor)node;
483 constructor.Body.Insert(GetIndexAfterSuperInvocation(constructor.Body),
484 CodeBuilder.CreateMethodInvocation(
485 CodeBuilder.CreateSelfReference((IType)type.Entity),
486 initializer));
491 int GetIndexAfterSuperInvocation(Block body)
493 int index = 0;
494 foreach (Statement s in body.Statements)
496 if (NodeType.ExpressionStatement == s.NodeType)
498 Expression expression = ((ExpressionStatement)s).Expression;
499 if (NodeType.MethodInvocationExpression == expression.NodeType)
501 if (NodeType.SuperLiteralExpression == ((MethodInvocationExpression)expression).Target.NodeType)
503 return index + 1;
507 ++index;
509 return 0;
512 Constructor FindStaticConstructor(TypeDefinition type)
514 foreach (TypeMember member in type.Members)
516 if (member.IsStatic && NodeType.Constructor == member.NodeType)
518 return (Constructor)member;
521 return null;
524 Constructor GetStaticConstructor(TypeDefinition type)
526 Constructor constructor = FindStaticConstructor(type);
527 if (null == constructor)
529 constructor = CreateStaticConstructor(type);
531 return constructor;
534 Constructor CreateStaticConstructor(TypeDefinition type)
536 Constructor constructor = new Constructor();
537 constructor.Entity = new InternalConstructor(TypeSystemServices, constructor);
538 constructor.Modifiers = TypeMemberModifiers.Public|TypeMemberModifiers.Static;
539 type.Members.Add(constructor);
540 MarkVisited(constructor);
541 return constructor;
544 void AddFieldInitializerToStaticConstructor(int index, Field node)
546 Constructor constructor = GetStaticConstructor(node.DeclaringType);
547 Statement stmt = CodeBuilder.CreateFieldAssignment(node, node.Initializer);
548 constructor.Body.Statements.Insert(index, stmt);
549 node.Initializer = null;
552 void CheckRuntimeMethod(Method method)
554 if (method.Body.Statements.Count > 0)
556 Error(CompilerErrorFactory.RuntimeMethodBodyMustBeEmpty(method, method.FullName));
560 override public void OnConstructor(Constructor node)
562 if (WasVisited(node))
564 return;
566 MarkVisited(node);
568 Visit(node.Attributes);
569 Visit(node.Parameters);
571 InternalConstructor entity = (InternalConstructor)node.Entity;
572 ProcessMethodBody(entity);
574 if (node.IsRuntime)
576 CheckRuntimeMethod(node);
578 else
580 if (entity.DeclaringType.IsValueType)
582 if (0 == node.Parameters.Count &&
583 !node.IsSynthetic)
585 Error(
586 CompilerErrorFactory.ValueTypesCannotDeclareParameterlessConstructors(node));
589 else if (
590 !entity.HasSelfCall &&
591 !entity.HasSuperCall &&
592 !entity.IsStatic)
594 IType baseType = entity.DeclaringType.BaseType;
595 IConstructor super = GetCorrectConstructor(node, baseType, EmptyExpressionCollection);
596 if (null != super)
598 node.Body.Statements.Insert(0,
599 CodeBuilder.CreateSuperConstructorInvocation(super));
605 override public void LeaveParameterDeclaration(ParameterDeclaration node)
607 AssertIdentifierName(node, node.Name);
608 CheckParameterType(node.Type);
611 void CheckParameterType(TypeReference type)
613 if (type.Entity != TypeSystemServices.VoidType) return;
614 Error(CompilerErrorFactory.InvalidParameterType(type, type.Entity.ToString()));
617 void CheckFieldType(TypeReference type)
619 if (type.Entity != TypeSystemServices.VoidType) return;
620 Error(CompilerErrorFactory.InvalidFieldType(type, type.Entity.ToString()));
623 void CheckDeclarationType(TypeReference type)
625 if (type.Entity != TypeSystemServices.VoidType) return;
626 Error(CompilerErrorFactory.InvalidDeclarationType(type, type.Entity.ToString()));
629 override public void OnBlockExpression(BlockExpression node)
631 if (WasVisited(node)) return;
632 MarkVisited(node);
634 Method closure = CodeBuilder.CreateMethod(
635 ClosureNameFor(node),
636 Unknown.Default,
637 ClosureModifiers());
639 MarkVisited(closure);
641 InternalMethod closureEntity = (InternalMethod)closure.Entity;
642 closure.LexicalInfo = node.LexicalInfo;
643 closure.Parameters = node.Parameters;
644 closure.Body = node.Body;
646 _currentMethod.Method.DeclaringType.Members.Add(closure);
648 CodeBuilder.BindParameterDeclarations(_currentMethod.IsStatic, closure);
650 // check for invalid names and
651 // resolve parameter types
652 Visit(closure.Parameters);
654 if (node.ContainsAnnotation("inline"))
656 AddOptionalReturnStatement(node.Body);
659 // Connects the closure method namespace with the current
660 NamespaceDelegator ns = new NamespaceDelegator(CurrentNamespace, closureEntity);
661 ProcessMethodBody(closureEntity, ns);
662 TryToResolveReturnType(closureEntity);
664 node.ExpressionType = closureEntity.Type;
665 node.Entity = closureEntity;
668 private TypeMemberModifiers ClosureModifiers()
670 TypeMemberModifiers modifiers = TypeMemberModifiers.Internal;
671 if (_currentMethod.IsStatic)
673 modifiers |= TypeMemberModifiers.Static;
675 return modifiers;
678 private string ClosureNameFor(BlockExpression block)
680 string closureHint = (block["ClosureName"] as string) ?? "closure";
681 return _currentMethod.Name + "$" + closureHint + "$" + _context.AllocIndex();
684 private void AddOptionalReturnStatement(Block body)
686 if (body.Statements.Count != 1) return;
687 ExpressionStatement stmt = body.Statements[0] as ExpressionStatement;
688 if (null == stmt) return;
690 ReturnStatement rs = new ReturnStatement(stmt.LexicalInfo, stmt.Expression, null);
691 rs.Annotate(OptionalReturnStatementAnnotation);
692 body.Replace(stmt, rs);
695 override public void OnMethod(Method method)
697 if (WasVisited(method)) return;
698 MarkVisited(method);
700 Visit(method.Attributes);
701 Visit(method.Parameters);
702 Visit(method.ReturnType);
703 Visit(method.ReturnTypeAttributes);
705 bool ispinvoke = GetEntity(method).IsPInvoke;
706 if (method.IsRuntime || ispinvoke)
708 CheckRuntimeMethod(method);
709 if (ispinvoke)
711 method.Modifiers |= TypeMemberModifiers.Static;
714 else
718 PushMember(method);
719 ProcessRegularMethod(method);
721 finally
723 PopMember();
728 void CheckIfIsMethodOverride(InternalMethod entity)
730 if (entity.IsStatic) return;
732 IMethod overriden = FindMethodOverride(entity);
733 if (null == overriden) return;
735 ProcessMethodOverride(entity, overriden);
738 IMethod FindPropertyAccessorOverride(Property property, Method accessor)
740 IProperty baseProperty = ((InternalProperty)property.Entity).Override;
741 if (null == baseProperty) return null;
743 IMethod baseMethod = null;
744 if (property.Getter == accessor)
746 baseMethod = baseProperty.GetGetMethod();
748 else
750 baseMethod = baseProperty.GetSetMethod();
753 if (null != baseMethod)
755 IMethod accessorEntity = (IMethod)accessor.Entity;
756 if (TypeSystemServices.CheckOverrideSignature(accessorEntity, baseMethod))
758 return baseMethod;
762 return null;
765 IMethod FindMethodOverride(InternalMethod entity)
767 Method method = entity.Method;
768 if (NodeType.Property == method.ParentNode.NodeType)
770 return FindPropertyAccessorOverride((Property)method.ParentNode, method);
773 IType baseType = entity.DeclaringType.BaseType;
774 IEntity candidates = NameResolutionService.Resolve(baseType, entity.Name, EntityType.Method);
775 if (null != candidates)
777 IMethod baseMethod = null;
778 if (EntityType.Method == candidates.EntityType)
780 IMethod candidate = (IMethod)candidates;
781 if (TypeSystemServices.CheckOverrideSignature(entity, candidate))
783 baseMethod = candidate;
786 else if (EntityType.Ambiguous == candidates.EntityType)
788 IEntity[] entities = ((Ambiguous)candidates).Entities;
789 foreach (IMethod candidate in entities)
791 if (TypeSystemServices.CheckOverrideSignature(entity, candidate))
793 baseMethod = candidate;
794 break;
798 if (null != baseMethod)
800 EnsureRelatedNodeWasVisited(method, baseMethod);
802 return baseMethod;
804 return null;
807 void ResolveMethodOverride(InternalMethod entity)
809 IMethod baseMethod = FindMethodOverride(entity);
810 if (null == baseMethod)
812 Error(CompilerErrorFactory.NoMethodToOverride(entity.Method, entity.ToString()));
814 else
816 if (!baseMethod.IsVirtual)
818 CantOverrideNonVirtual(entity.Method, baseMethod);
820 else
822 ProcessMethodOverride(entity, baseMethod);
827 void ProcessMethodOverride(InternalMethod entity, IMethod baseMethod)
829 if (TypeSystemServices.IsUnknown(entity.ReturnType))
831 entity.Method.ReturnType = CodeBuilder.CreateTypeReference(entity.Method.LexicalInfo, baseMethod.ReturnType);
833 else
835 if (baseMethod.ReturnType != entity.ReturnType)
837 Error(CompilerErrorFactory.InvalidOverrideReturnType(
838 entity.Method.ReturnType,
839 baseMethod.FullName,
840 baseMethod.ReturnType.ToString(),
841 entity.ReturnType.ToString()));
844 SetOverride(entity, baseMethod);
847 void CantOverrideNonVirtual(Method method, IMethod baseMethod)
849 Error(CompilerErrorFactory.CantOverrideNonVirtual(method, baseMethod.ToString()));
852 void SetPropertyAccessorOverride(Method accessor)
854 if (null != accessor)
856 accessor.Modifiers |= TypeMemberModifiers.Override;
860 IProperty ResolvePropertyOverride(IProperty p, IEntity[] candidates)
862 foreach (IEntity candidate in candidates)
864 if (EntityType.Property != candidate.EntityType) continue;
865 IProperty candidateProperty = (IProperty)candidate;
866 if (CheckOverrideSignature(p, candidateProperty))
868 return candidateProperty;
871 return null;
874 bool CheckOverrideSignature(IProperty p, IProperty candidate)
876 return TypeSystemServices.CheckOverrideSignature(p.GetParameters(), candidate.GetParameters());
879 void ResolvePropertyOverride(Property property)
881 InternalProperty entity = (InternalProperty)property.Entity;
882 IType baseType = entity.DeclaringType.BaseType;
883 IEntity baseProperties = NameResolutionService.Resolve(baseType, property.Name, EntityType.Property);
884 if (null != baseProperties)
886 if (EntityType.Property == baseProperties.EntityType)
888 IProperty candidate = (IProperty)baseProperties;
889 if (CheckOverrideSignature(entity, candidate))
891 entity.Override = candidate;
894 else if (EntityType.Ambiguous == baseProperties.EntityType)
896 entity.Override = ResolvePropertyOverride(entity, ((Ambiguous)baseProperties).Entities);
900 if (null != entity.Override)
902 EnsureRelatedNodeWasVisited(property, entity.Override);
903 if (property.IsOverride)
905 SetPropertyAccessorOverride(property.Getter);
906 SetPropertyAccessorOverride(property.Setter);
908 else
910 if (null != entity.Override.GetGetMethod())
912 SetPropertyAccessorOverride(property.Getter);
914 if (null != entity.Override.GetSetMethod())
916 SetPropertyAccessorOverride(property.Setter);
920 if (null == property.Type)
922 property.Type = CodeBuilder.CreateTypeReference(entity.Override.Type);
927 void SetOverride(InternalMethod entity, IMethod baseMethod)
929 TraceOverride(entity.Method, baseMethod);
931 entity.Overriden = baseMethod;
932 entity.Method.Modifiers |= TypeMemberModifiers.Override;
936 void TraceOverride(Method method, IMethod baseMethod)
938 _context.TraceInfo("{0}: Method '{1}' overrides '{2}'", method.LexicalInfo, method.Name, baseMethod);
941 class ReturnExpressionFinder : DepthFirstVisitor
943 bool _hasReturnStatements = false;
945 bool _hasYieldStatements = false;
947 public ReturnExpressionFinder(Method node)
949 Visit(node.Body);
952 public bool HasReturnStatements
956 return _hasReturnStatements;
960 public bool HasYieldStatements
964 return _hasYieldStatements;
968 public override void OnReturnStatement(ReturnStatement node)
970 _hasReturnStatements |= (null != node.Expression);
973 public override void OnYieldStatement(YieldStatement node)
975 _hasYieldStatements = true;
979 bool DontHaveReturnExpressionsNorYield(Method node)
981 ReturnExpressionFinder finder = new ReturnExpressionFinder(node);
982 return !(finder.HasReturnStatements || finder.HasYieldStatements);
985 void PreProcessMethod(Method node)
987 if (WasAlreadyPreProcessed(node)) return;
988 MarkPreProcessed(node);
990 InternalMethod entity = (InternalMethod)GetEntity(node);
991 if (node.IsOverride)
993 ResolveMethodOverride(entity);
995 else
997 CheckIfIsMethodOverride(entity);
998 if (TypeSystemServices.IsUnknown(entity.ReturnType))
1000 if (DontHaveReturnExpressionsNorYield(node))
1002 node.ReturnType = CodeBuilder.CreateTypeReference(node.LexicalInfo, TypeSystemServices.VoidType);
1008 static readonly object PreProcessedKey = new object();
1010 private bool WasAlreadyPreProcessed(Method node)
1012 return node.ContainsAnnotation(PreProcessedKey);
1015 private void MarkPreProcessed(Method node)
1017 node[PreProcessedKey] = PreProcessedKey;
1020 void ProcessRegularMethod(Method node)
1022 PreProcessMethod(node);
1024 InternalMethod entity = (InternalMethod) GetEntity(node);
1025 ProcessMethodBody(entity);
1027 PostProcessMethod(node);
1030 private void PostProcessMethod(Method node)
1032 bool parentIsClass = node.DeclaringType.NodeType == NodeType.ClassDefinition;
1033 if (!parentIsClass) return;
1035 InternalMethod entity = (InternalMethod)GetEntity(node);
1036 if (TypeSystemServices.IsUnknown(entity.ReturnType))
1038 TryToResolveReturnType(entity);
1040 else
1042 if (entity.IsGenerator)
1044 CheckGeneratorReturnType(node, entity.ReturnType);
1045 CheckGeneratorYieldType(entity, entity.ReturnType);
1048 CheckGeneratorCantReturnValues(entity);
1051 void CheckGeneratorCantReturnValues(InternalMethod entity)
1053 if (!entity.IsGenerator) return;
1054 if (null == entity.ReturnExpressions) return;
1056 foreach (Expression e in entity.ReturnExpressions)
1058 Error(CompilerErrorFactory.GeneratorCantReturnValue(e));
1062 void CheckGeneratorReturnType(Method method, IType returnType)
1064 bool validReturnType =
1065 (TypeSystemServices.IEnumerableType == returnType ||
1066 TypeSystemServices.IEnumeratorType == returnType ||
1067 TypeSystemServices.IsSystemObject(returnType) ||
1068 CheckGenericGeneratorReturnType(returnType));
1070 if (!validReturnType)
1072 Error(CompilerErrorFactory.InvalidGeneratorReturnType(method.ReturnType));
1076 bool CheckGenericGeneratorReturnType(IType returnType)
1078 return returnType.ConstructedInfo != null &&
1079 (returnType.ConstructedInfo.GenericDefinition == TypeSystemServices.IEnumerableGenericType ||
1080 returnType.ConstructedInfo.GenericDefinition == TypeSystemServices.IEnumeratorGenericType);
1083 void CheckGeneratorYieldType(InternalMethod method, IType returnType)
1085 if (CheckGenericGeneratorReturnType(returnType))
1087 IType returnElementType = returnType.ConstructedInfo.GenericArguments[0];
1089 foreach (Expression yieldExpression in method.YieldExpressions)
1091 IType yieldType = yieldExpression.ExpressionType;
1092 if (!returnElementType.IsAssignableFrom(yieldType) &&
1093 !TypeSystemServices.CanBeReachedByDownCastOrPromotion(returnElementType, yieldType))
1095 Error(CompilerErrorFactory.YieldTypeDoesNotMatchReturnType(
1096 yieldExpression, yieldType.ToString(), returnElementType.ToString()));
1102 void ProcessMethodBody(InternalMethod entity)
1104 ProcessMethodBody(entity, entity);
1107 void ProcessMethodBody(InternalMethod entity, INamespace ns)
1109 ProcessNodeInMethodContext(entity, ns, entity.Method.Body);
1110 if (entity.IsGenerator) CreateGeneratorSkeleton(entity);
1113 void ProcessNodeInMethodContext(InternalMethod entity, INamespace ns, Node node)
1115 PushMethodInfo(entity);
1116 EnterNamespace(ns);
1119 Visit(node);
1121 finally
1123 LeaveNamespace();
1124 PopMethodInfo();
1128 void ResolveGeneratorReturnType(InternalMethod entity)
1130 Method method = entity.Method;
1132 // Make method return a generic IEnumerable
1133 IType itemType = (IType)method["GeneratorItemType"];
1134 if (TypeSystemServices.VoidType == itemType)
1136 // circunvent exception in MakeGenericType
1137 method.ReturnType = CodeBuilder.CreateTypeReference(TypeSystemServices.ErrorEntity);
1138 return;
1141 IType returnType = GetGeneratorReturnType(itemType);
1142 method.ReturnType = CodeBuilder.CreateTypeReference(returnType);
1146 protected virtual IType GetGeneratorReturnType(IType itemType)
1148 IType enumerableType = TypeSystemServices.IEnumerableGenericType;
1149 return enumerableType.GenericInfo.ConstructType(itemType);
1152 void TryToResolveReturnType(InternalMethod entity)
1154 if (entity.IsGenerator)
1156 ResolveGeneratorReturnType(entity);
1158 else
1160 if (CanResolveReturnType(entity))
1162 ResolveReturnType(entity);
1167 override public void OnSuperLiteralExpression(SuperLiteralExpression node)
1169 if (!AstUtil.IsTargetOfMethodInvocation(node))
1171 node.ExpressionType = _currentMethod.DeclaringType.BaseType;
1172 return;
1175 if (EntityType.Constructor == _currentMethod.EntityType)
1177 // TODO: point to super ctor
1178 node.Entity = _currentMethod;
1179 return;
1182 if (null == _currentMethod.Overriden)
1184 Error(node,
1185 CompilerErrorFactory.MethodIsNotOverride(node, _currentMethod.ToString()));
1186 return;
1189 node.Entity = _currentMethod;
1192 bool CanResolveReturnType(InternalMethod tag)
1194 ExpressionCollection expressions = tag.ReturnExpressions;
1195 if (null != expressions)
1197 foreach (Expression expression in expressions)
1199 IType type = expression.ExpressionType;
1200 if (null == type || TypeSystemServices.IsUnknown(type))
1202 return false;
1206 return true;
1209 TypeReference GetMostGenericTypeReference(ExpressionCollection expressions)
1211 IType type = MapNullToObject(GetMostGenericType(expressions));
1212 return CodeBuilder.CreateTypeReference(type);
1215 void ResolveReturnType(InternalMethod entity)
1217 Method method = entity.Method;
1218 if (null == entity.ReturnExpressions)
1220 method.ReturnType = CodeBuilder.CreateTypeReference(TypeSystemServices.VoidType);
1222 else
1224 method.ReturnType = GetMostGenericTypeReference(entity.ReturnExpressions);
1226 TraceReturnType(method, entity);
1229 IType MapNullToObject(IType type)
1231 if (Null.Default == type)
1233 return TypeSystemServices.ObjectType;
1235 return type;
1238 IType GetMostGenericType(IType lhs, IType rhs)
1240 return TypeSystemServices.GetMostGenericType(lhs, rhs);
1243 IType GetMostGenericType(ExpressionCollection args)
1245 IType type = GetConcreteExpressionType(args[0]);
1246 for (int i=1; i<args.Count; ++i)
1248 IType newType = GetConcreteExpressionType(args[i]);
1250 if (type == newType)
1252 continue;
1255 type = GetMostGenericType(type, newType);
1256 if (TypeSystemServices.IsSystemObject(type))
1258 break;
1261 return type;
1264 override public void OnBoolLiteralExpression(BoolLiteralExpression node)
1266 BindExpressionType(node, TypeSystemServices.BoolType);
1269 override public void OnTimeSpanLiteralExpression(TimeSpanLiteralExpression node)
1271 BindExpressionType(node, TypeSystemServices.TimeSpanType);
1274 override public void OnIntegerLiteralExpression(IntegerLiteralExpression node)
1276 if (node.IsLong)
1278 BindExpressionType(node, TypeSystemServices.LongType);
1280 else
1282 BindExpressionType(node, TypeSystemServices.IntType);
1286 override public void OnDoubleLiteralExpression(DoubleLiteralExpression node)
1288 BindExpressionType(node, node.IsSingle ? TypeSystemServices.SingleType : TypeSystemServices.DoubleType);
1291 override public void OnStringLiteralExpression(StringLiteralExpression node)
1293 BindExpressionType(node, TypeSystemServices.StringType);
1296 override public void OnCharLiteralExpression(CharLiteralExpression node)
1298 string value = node.Value;
1299 if (null == value || 1 != value.Length)
1301 Errors.Add(CompilerErrorFactory.InvalidCharLiteral(node, value));
1303 BindExpressionType(node, TypeSystemServices.CharType);
1306 IEntity[] GetSetMethods(IEntity[] entities)
1308 List setMethods = new List();
1309 for (int i=0; i<entities.Length; ++i)
1311 IProperty property = entities[i] as IProperty;
1312 if (null != property)
1314 IMethod setter = property.GetSetMethod();
1315 if (null != setter)
1317 setMethods.AddUnique(setter);
1321 return ToEntityArray(setMethods);
1324 IEntity[] GetGetMethods(IEntity[] entities)
1326 List getMethods = new List();
1327 for (int i=0; i<entities.Length; ++i)
1329 IProperty property = entities[i] as IProperty;
1330 if (null != property)
1332 IMethod getter = property.GetGetMethod();
1333 if (null != getter)
1335 getMethods.AddUnique(getter);
1339 return ToEntityArray(getMethods);
1342 private static IEntity[] ToEntityArray(List entities)
1344 return (IEntity[])entities.ToArray(new IEntity[entities.Count]);
1347 void CheckNoComplexSlicing(SlicingExpression node)
1349 if (AstUtil.IsComplexSlicing(node))
1351 NotImplemented(node, "complex slicing");
1355 protected MethodInvocationExpression CreateEquals(BinaryExpression node)
1357 return CodeBuilder.CreateMethodInvocation(RuntimeServices_EqualityOperator, node.Left, node.Right);
1360 IntegerLiteralExpression CreateIntegerLiteral(long value)
1362 IntegerLiteralExpression expression = new IntegerLiteralExpression(value);
1363 Visit(expression);
1364 return expression;
1367 bool CheckComplexSlicingParameters(SlicingExpression node)
1369 foreach (Slice slice in node.Indices)
1371 if (!CheckComplexSlicingParameters(slice))
1373 return false;
1376 return true;
1379 bool CheckComplexSlicingParameters(Slice node)
1381 if (null != node.Step)
1383 NotImplemented(node, "slicing step");
1384 return false;
1387 if (OmittedExpression.Default == node.Begin)
1389 node.Begin = CreateIntegerLiteral(0);
1391 else
1393 if (!AssertTypeCompatibility(node.Begin, TypeSystemServices.IntType, GetExpressionType(node.Begin)))
1395 return false;
1399 if (null != node.End && OmittedExpression.Default != node.End)
1401 if (!AssertTypeCompatibility(node.End, TypeSystemServices.IntType, GetExpressionType(node.End)))
1403 return false;
1407 return true;
1410 void BindComplexListSlicing(SlicingExpression node)
1412 Slice slice = node.Indices[0];
1414 if (CheckComplexSlicingParameters(slice))
1416 MethodInvocationExpression mie = null;
1418 if (null == slice.End || slice.End == OmittedExpression.Default)
1420 mie = CodeBuilder.CreateMethodInvocation(node.Target, List_GetRange1);
1421 mie.Arguments.Add(slice.Begin);
1423 else
1425 mie = CodeBuilder.CreateMethodInvocation(node.Target, List_GetRange2);
1426 mie.Arguments.Add(slice.Begin);
1427 mie.Arguments.Add(slice.End);
1429 node.ParentNode.Replace(node, mie);
1433 void BindComplexArraySlicing(SlicingExpression node)
1435 if (AstUtil.IsLhsOfAssignment(node))
1437 return;
1440 if (CheckComplexSlicingParameters(node))
1442 if (node.Indices.Count > 1)
1444 IArrayType arrayType = (IArrayType)GetExpressionType(node.Target);
1445 MethodInvocationExpression mie = null;
1446 ArrayLiteralExpression collapse = new ArrayLiteralExpression();
1447 ArrayLiteralExpression ranges = new ArrayLiteralExpression();
1448 int collapseCount = 0;
1449 for (int i = 0; i < node.Indices.Count; i++)
1451 ranges.Items.Add(node.Indices[i].Begin);
1452 if (node.Indices[i].End == null ||
1453 node.Indices[i].End == OmittedExpression.Default)
1455 BinaryExpression end = new BinaryExpression(BinaryOperatorType.Addition,
1456 node.Indices[i].Begin,
1457 new IntegerLiteralExpression(1));
1458 ranges.Items.Add(end);
1459 BindExpressionType(end, GetExpressionType(node.Indices[i].Begin));
1460 collapse.Items.Add(new BoolLiteralExpression(true));
1461 collapseCount++;
1463 else
1465 ranges.Items.Add(node.Indices[i].End);
1466 collapse.Items.Add(new BoolLiteralExpression(false));
1469 mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetMultiDimensionalRange1, node.Target, ranges);
1470 mie.Arguments.Add(collapse);
1472 BindExpressionType(ranges, TypeSystemServices.Map(typeof(int[])));
1473 BindExpressionType(collapse, TypeSystemServices.Map(typeof(bool[])));
1474 BindExpressionType(mie, TypeSystemServices.GetArrayType(arrayType.GetElementType(), node.Indices.Count - collapseCount));
1475 node.ParentNode.Replace(node, mie);
1477 else
1479 Slice slice = node.Indices[0];
1481 if (CheckComplexSlicingParameters(slice))
1483 MethodInvocationExpression mie = null;
1485 if (null == slice.End || slice.End == OmittedExpression.Default)
1487 mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetRange1, node.Target, slice.Begin);
1489 else
1491 mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetRange2, node.Target, slice.Begin, slice.End);
1494 BindExpressionType(mie, GetExpressionType(node.Target));
1495 node.ParentNode.Replace(node, mie);
1501 bool NeedsNormalization(Expression index)
1503 if (NodeType.IntegerLiteralExpression == index.NodeType)
1505 return ((IntegerLiteralExpression)index).Value < 0;
1507 return true;
1510 void BindComplexStringSlicing(SlicingExpression node)
1512 Slice slice = node.Indices[0];
1514 if (CheckComplexSlicingParameters(slice))
1516 MethodInvocationExpression mie = null;
1518 if (null == slice.End || slice.End == OmittedExpression.Default)
1520 if (NeedsNormalization(slice.Begin))
1522 mie = CodeBuilder.CreateEvalInvocation(node.LexicalInfo);
1523 mie.ExpressionType = TypeSystemServices.StringType;
1525 InternalLocal temp = DeclareTempLocal(TypeSystemServices.StringType);
1526 mie.Arguments.Add(
1527 CodeBuilder.CreateAssignment(
1528 CodeBuilder.CreateReference(temp),
1529 node.Target));
1531 mie.Arguments.Add(
1532 CodeBuilder.CreateMethodInvocation(
1533 CodeBuilder.CreateReference(temp),
1534 String_Substring_Int,
1535 CodeBuilder.CreateMethodInvocation(
1536 RuntimeServices_NormalizeStringIndex,
1537 CodeBuilder.CreateReference(temp),
1538 slice.Begin)));
1540 else
1542 mie = CodeBuilder.CreateMethodInvocation(node.Target, String_Substring_Int, slice.Begin);
1545 else
1547 mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_Mid, node.Target, slice.Begin, slice.End);
1550 node.ParentNode.Replace(node, mie);
1554 bool IsIndexedProperty(Expression expression)
1556 IEntity entity = expression.Entity;
1557 if (null != entity)
1559 return IsIndexedProperty(entity);
1561 return false;
1564 override public void LeaveSlicingExpression(SlicingExpression node)
1566 if (IsAmbiguous(node.Target.Entity))
1568 BindIndexedPropertySlicing(node);
1569 return;
1572 // target[indices]
1573 IType targetType = GetExpressionType(node.Target);
1574 if (TypeSystemServices.IsError(targetType))
1576 Error(node);
1577 return;
1580 if (IsIndexedProperty(node.Target))
1582 BindIndexedPropertySlicing(node);
1584 else
1586 if (targetType.IsArray)
1588 IArrayType arrayType = (IArrayType)targetType;
1589 if (arrayType.GetArrayRank() != node.Indices.Count)
1591 Error(node, CompilerErrorFactory.InvalidArrayRank(node, node.Target.ToString(), arrayType.GetArrayRank(), node.Indices.Count));
1594 if (AstUtil.IsComplexSlicing(node))
1596 BindComplexArraySlicing(node);
1598 else
1600 if (arrayType.GetArrayRank() > 1)
1602 BindMultiDimensionalArraySlicing(node);
1604 else
1606 BindExpressionType(node, arrayType.GetElementType());
1610 else
1612 if (AstUtil.IsComplexSlicing(node))
1614 if (TypeSystemServices.StringType == targetType)
1616 BindComplexStringSlicing(node);
1618 else
1620 if (TypeSystemServices.ListType.IsAssignableFrom(targetType))
1622 BindComplexListSlicing(node);
1624 else
1626 NotImplemented(node, "complex slicing for anything but lists, arrays and strings");
1630 else
1632 IEntity member = targetType.GetDefaultMember();
1633 if (null == member)
1635 Error(node, CompilerErrorFactory.TypeDoesNotSupportSlicing(node.Target, targetType.ToString()));
1637 else
1639 node.Target = new MemberReferenceExpression(node.LexicalInfo, node.Target, member.Name);
1640 node.Target.Entity = member;
1641 // to be resolved later
1642 node.Target.ExpressionType = Null.Default;
1643 SliceMember(node, member);
1650 private void BindIndexedPropertySlicing(SlicingExpression node)
1652 CheckNoComplexSlicing(node);
1653 SliceMember(node, node.Target.Entity);
1656 private bool IsAmbiguous(IEntity entity)
1658 return null != entity && EntityType.Ambiguous == entity.EntityType;
1661 bool IsIndexedProperty(IEntity tag)
1663 return EntityType.Property == tag.EntityType &&
1664 ((IProperty)tag).GetParameters().Length > 0;
1667 void BindMultiDimensionalArraySlicing(SlicingExpression node)
1669 if (AstUtil.IsLhsOfAssignment(node))
1671 // leave it to LeaveBinaryExpression to resolve
1672 return;
1675 MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation(
1676 node.Target,
1677 TypeSystemServices.Map(
1678 typeof(Array).GetMethod("GetValue", new Type[] { typeof(int[]) })));
1679 for (int i = 0; i < node.Indices.Count; i++)
1681 mie.Arguments.Add(node.Indices[i].Begin);
1684 IType elementType = node.Target.ExpressionType.GetElementType();
1685 node.ParentNode.Replace(node, CodeBuilder.CreateCast(elementType, mie));
1688 void SliceMember(SlicingExpression node, IEntity member)
1690 EnsureRelatedNodeWasVisited(node, member);
1691 if (AstUtil.IsLhsOfAssignment(node))
1693 // leave it to LeaveBinaryExpression to resolve
1694 Bind(node, member);
1695 return;
1698 MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo);
1699 foreach (Slice index in node.Indices)
1701 mie.Arguments.Add(index.Begin);
1704 IMethod getter = null;
1705 if (EntityType.Ambiguous == member.EntityType)
1707 IEntity result = ResolveAmbiguousPropertyReference((ReferenceExpression)node.Target, (Ambiguous)member, mie.Arguments);
1708 IProperty found = result as IProperty;
1709 if (null != found)
1711 getter = found.GetGetMethod();
1713 else if (EntityType.Ambiguous == result.EntityType)
1715 Error(node);
1716 return;
1719 else if (EntityType.Property == member.EntityType)
1721 getter = ((IProperty)member).GetGetMethod();
1724 if (null != getter)
1726 if (AssertParameters(node, getter, mie.Arguments))
1728 Expression target = GetIndexedPropertySlicingTarget(node);
1730 mie.Target = CodeBuilder.CreateMemberReference(target, getter);
1731 BindExpressionType(mie, getter.ReturnType);
1733 node.ParentNode.Replace(node, mie);
1735 else
1737 Error(node);
1740 else
1742 NotImplemented(node, "slice for anything but arrays and default properties");
1746 private Expression GetIndexedPropertySlicingTarget(SlicingExpression node)
1748 Expression target = node.Target;
1749 MemberReferenceExpression mre = target as MemberReferenceExpression;
1750 if (null != mre) return mre.Target;
1751 return CreateSelfReference();
1754 override public void LeaveExpressionInterpolationExpression(ExpressionInterpolationExpression node)
1756 BindExpressionType(node, TypeSystemServices.StringType);
1759 override public void LeaveListLiteralExpression(ListLiteralExpression node)
1761 BindExpressionType(node, TypeSystemServices.ListType);
1762 TypeSystemServices.MapToConcreteExpressionTypes(node.Items);
1765 override public void OnExtendedGeneratorExpression(ExtendedGeneratorExpression node)
1767 BlockExpression block = new BlockExpression(node.LexicalInfo);
1769 Block body = block.Body;
1770 Expression e = node.Items[0].Expression;
1771 foreach (GeneratorExpression ge in node.Items)
1773 ForStatement fs = new ForStatement(ge.LexicalInfo);
1774 fs.Iterator = ge.Iterator;
1775 fs.Declarations = ge.Declarations;
1777 body.Add(fs);
1779 if (null == ge.Filter)
1781 body = fs.Block;
1783 else
1785 fs.Block.Add(
1786 NormalizeStatementModifiers.MapStatementModifier(ge.Filter, out body));
1791 body.Add(new YieldStatement(e.LexicalInfo, e));
1793 MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo);
1794 mie.Target = block;
1796 Node parentNode = node.ParentNode;
1797 bool isGenerator = AstUtil.IsListMultiGenerator(parentNode);
1798 parentNode.Replace(node, mie);
1799 mie.Accept(this);
1801 if (isGenerator)
1803 parentNode.ParentNode.Replace(
1804 parentNode,
1805 CodeBuilder.CreateConstructorInvocation(
1806 TypeSystemServices.Map(ProcessGenerators.List_IEnumerableConstructor),
1807 mie));
1811 override public void OnGeneratorExpression(GeneratorExpression node)
1813 Visit(node.Iterator);
1814 node.Iterator = ProcessIterator(node.Iterator, node.Declarations);
1816 EnterNamespace(new DeclarationsNamespace(CurrentNamespace, TypeSystemServices, node.Declarations));
1817 Visit(node.Filter);
1818 Visit(node.Expression);
1819 LeaveNamespace();
1821 BooClassBuilder generatorType = CreateGeneratorSkeleton(node);
1823 BindExpressionType(node, generatorType.Entity);
1826 void CreateGeneratorSkeleton(InternalMethod entity)
1828 Method method = entity.Method;
1829 IType itemType = GetGeneratorItemType(entity);
1830 BooClassBuilder builder = CreateGeneratorSkeleton(method, method, itemType);
1831 method.DeclaringType.Members.Add(builder.ClassDefinition);
1832 // TypeSystemServices.AddCompilerGeneratedType(builder.ClassDefinition);
1835 private IType GetGeneratorItemType(InternalMethod entity)
1837 IType itemType = null;
1839 if (CheckGenericGeneratorReturnType(entity.ReturnType))
1841 itemType = entity.ReturnType.ConstructedInfo.GenericArguments[0];
1843 if (itemType == null)
1845 ExpressionCollection yieldExpressions = entity.YieldExpressions;
1847 itemType = yieldExpressions.Count > 0
1848 ? GetMostGenericType(yieldExpressions)
1849 : TypeSystemServices.ObjectType;
1851 return itemType;
1854 BooClassBuilder CreateGeneratorSkeleton(GeneratorExpression node)
1856 BooClassBuilder builder = CreateGeneratorSkeleton(node, _currentMethod.Method, GetConcreteExpressionType(node.Expression));
1857 _currentMethod.Method.DeclaringType.Members.Add(builder.ClassDefinition);
1858 return builder;
1861 protected IType GetConstructedType(IType genericType, IType argType)
1863 return genericType.GenericInfo.ConstructType(argType);
1866 BooClassBuilder CreateGeneratorSkeleton(Node sourceNode, Method method, IType generatorItemType)
1868 // create the class skeleton for type inference to work
1869 BooClassBuilder builder = CodeBuilder.CreateClass(
1870 string.Format("{0}${1}", method.Name, _context.AllocIndex()),
1871 TypeMemberModifiers.Internal|TypeMemberModifiers.Final);
1872 builder.LexicalInfo = sourceNode.LexicalInfo;
1873 builder.AddAttribute(CodeBuilder.CreateAttribute(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute)));
1875 BooMethodBuilder getEnumeratorBuilder = null;
1876 if (generatorItemType != TypeSystemServices.VoidType)
1878 builder.AddBaseType(
1879 TypeSystemServices.Map(typeof(GenericGenerator<>)).GenericInfo.ConstructType(generatorItemType));
1881 getEnumeratorBuilder = builder.AddVirtualMethod(
1882 "GetEnumerator",
1883 TypeSystemServices.IEnumeratorGenericType.GenericInfo.ConstructType(generatorItemType));
1885 getEnumeratorBuilder.Method.LexicalInfo = sourceNode.LexicalInfo;
1888 sourceNode["GeneratorClassBuilder"] = builder;
1889 sourceNode["GetEnumeratorBuilder"] = getEnumeratorBuilder;
1890 sourceNode["GeneratorItemType"] = generatorItemType;
1892 return builder;
1895 override public void LeaveHashLiteralExpression(HashLiteralExpression node)
1897 BindExpressionType(node, TypeSystemServices.HashType);
1898 foreach (ExpressionPair pair in node.Items)
1900 GetConcreteExpressionType(pair.First);
1901 GetConcreteExpressionType(pair.Second);
1905 override public void LeaveArrayLiteralExpression(ArrayLiteralExpression node)
1907 TypeSystemServices.MapToConcreteExpressionTypes(node.Items);
1908 IArrayType type = InferArrayType(node);
1909 BindExpressionType(node, type);
1910 if (null == node.Type)
1912 node.Type = (ArrayTypeReference)CodeBuilder.CreateTypeReference(type);
1914 else
1916 CheckItems(type.GetElementType(), node.Items);
1920 private IArrayType InferArrayType(ArrayLiteralExpression node)
1922 if (null != node.Type) return (IArrayType)node.Type.Entity;
1923 if (0 == node.Items.Count) return TypeSystemServices.ObjectArrayType;
1924 return TypeSystemServices.GetArrayType(GetMostGenericType(node.Items), 1);
1927 override public void LeaveDeclaration(Declaration node)
1929 if (null == node.Type) return;
1930 CheckDeclarationType(node.Type);
1933 override public void LeaveDeclarationStatement(DeclarationStatement node)
1935 IType type = GetDeclarationType(node);
1937 AssertDeclarationName(node.Declaration);
1939 IEntity localInfo = DeclareLocal(node, node.Declaration.Name, type);
1940 if (null != node.Initializer)
1942 IType itype = GetExpressionType(node.Initializer);
1943 AssertTypeCompatibility(node.Initializer, type, itype);
1945 if (TypeSystemServices.IsNullable(type) && !TypeSystemServices.IsNullable(itype))
1947 BindNullableInitializer(node, node.Initializer, type);
1950 node.ReplaceBy(
1951 new ExpressionStatement(
1952 CodeBuilder.CreateAssignment(
1953 node.LexicalInfo,
1954 CodeBuilder.CreateReference(localInfo),
1955 node.Initializer)));
1957 else
1959 node.ReplaceBy(
1960 new ExpressionStatement(
1961 CreateDefaultLocalInitializer(node, localInfo)));
1965 private IType GetDeclarationType(DeclarationStatement node)
1967 if (null != node.Declaration.Type) return GetType(node.Declaration.Type);
1969 return InferDeclarationType(node);
1972 private IType InferDeclarationType(DeclarationStatement node)
1974 if (null == node.Initializer) return TypeSystemServices.ObjectType;
1976 // The boo syntax does not require this check because
1977 // there's no way to create an untyped declaration statement.
1978 // This is here to support languages that do allow untyped variable
1979 // declarations (unityscript is such an example).
1980 return GetConcreteExpressionType(node.Initializer);
1983 virtual protected Expression CreateDefaultLocalInitializer(Node sourceNode, IEntity local)
1985 return CodeBuilder.CreateDefaultInitializer(
1986 sourceNode.LexicalInfo,
1987 (InternalLocal)local);
1990 override public void LeaveExpressionStatement(ExpressionStatement node)
1992 AssertHasSideEffect(node.Expression);
1995 override public void OnNullLiteralExpression(NullLiteralExpression node)
1997 BindExpressionType(node, Null.Default);
2000 override public void OnSelfLiteralExpression(SelfLiteralExpression node)
2002 if (null == _currentMethod)
2004 Error(node, CompilerErrorFactory.SelfOutsideMethod(node));
2006 else
2008 if (_currentMethod.IsStatic)
2010 if (NodeType.MemberReferenceExpression != node.ParentNode.NodeType)
2012 // if we are inside a MemberReferenceExpression
2013 // let the MemberReferenceExpression deal with it
2014 // as it can provide a better message
2015 Error(CompilerErrorFactory.ObjectRequired(node));
2018 node.Entity = _currentMethod;
2019 node.ExpressionType = _currentMethod.DeclaringType;
2023 override public void LeaveTypeofExpression(TypeofExpression node)
2025 BindExpressionType(node, TypeSystemServices.TypeType);
2028 override public void LeaveCastExpression(CastExpression node)
2030 IType fromType = GetExpressionType(node.Target);
2031 IType toType = GetType(node.Type);
2032 if (!TypeSystemServices.AreTypesRelated(toType, fromType) &&
2033 !(toType.IsInterface && !fromType.IsFinal) &&
2034 !(TypeSystemServices.IsIntegerNumber(toType) && TypeSystemServices.CanBeExplicitlyCastToInteger(fromType)) &&
2035 !(TypeSystemServices.IsIntegerNumber(fromType) && TypeSystemServices.CanBeExplicitlyCastToInteger(toType)))
2037 IMethod explicitOperator = TypeSystemServices.FindExplicitConversionOperator(fromType, toType);
2038 if (null != explicitOperator)
2040 node.ParentNode.Replace(
2041 node,
2042 CodeBuilder.CreateMethodInvocation(
2043 explicitOperator,
2044 node.Target));
2045 return;
2048 Error(
2049 CompilerErrorFactory.IncompatibleExpressionType(
2050 node,
2051 toType.ToString(),
2052 fromType.ToString()));
2054 BindExpressionType(node, toType);
2057 override public void LeaveTryCastExpression(TryCastExpression node)
2059 IType target = GetExpressionType(node.Target);
2060 IType toType = GetType(node.Type);
2062 if (target.IsValueType)
2064 Error(CompilerErrorFactory.CantCastToValueType(node.Target, target.ToString()));
2066 else if (toType.IsValueType)
2068 Error(CompilerErrorFactory.CantCastToValueType(node.Type, toType.ToString()));
2070 BindExpressionType(node, toType);
2073 protected Expression CreateMemberReferenceTarget(Node sourceNode, IMember member)
2075 Expression target = null;
2077 if (member.IsStatic)
2079 target = new ReferenceExpression(sourceNode.LexicalInfo, member.DeclaringType.FullName);
2080 Bind(target, member.DeclaringType);
2082 else
2084 //check if found entity can't possibly be a member of self:
2085 if (member.DeclaringType != CurrentType
2086 && !(CurrentType.IsSubclassOf(member.DeclaringType)))
2088 Error(
2089 CompilerErrorFactory.InstanceRequired(sourceNode,
2090 member.DeclaringType.ToString(),
2091 member.Name));
2093 target = new SelfLiteralExpression(sourceNode.LexicalInfo);
2095 BindExpressionType(target, member.DeclaringType);
2096 return target;
2099 protected MemberReferenceExpression MemberReferenceFromReference(ReferenceExpression node, IMember member)
2101 MemberReferenceExpression memberRef = new MemberReferenceExpression(node.LexicalInfo);
2102 memberRef.Name = node.Name;
2103 memberRef.Target = CreateMemberReferenceTarget(node, member);
2104 return memberRef;
2107 void ResolveMemberInfo(ReferenceExpression node, IMember member)
2109 MemberReferenceExpression memberRef = MemberReferenceFromReference(node, member);
2110 Bind(memberRef, member);
2111 node.ParentNode.Replace(node, memberRef);
2112 Visit(memberRef);
2115 override public void OnRELiteralExpression(RELiteralExpression node)
2117 if (null != node.Entity)
2119 return;
2122 IType type = TypeSystemServices.RegexType;
2123 BindExpressionType(node, type);
2125 if (NodeType.Field != node.ParentNode.NodeType)
2127 ReplaceByStaticFieldReference(node, "$re$" + _context.AllocIndex(), type);
2131 void ReplaceByStaticFieldReference(Expression node, string fieldName, IType type)
2133 Node parent = node.ParentNode;
2135 Field field = CodeBuilder.CreateField(fieldName, type);
2136 field.Modifiers = TypeMemberModifiers.Internal|TypeMemberModifiers.Static;
2137 field.Initializer = node;
2139 _currentMethod.Method.DeclaringType.Members.Add(field);
2140 parent.Replace(node, CodeBuilder.CreateReference(field));
2142 AddFieldInitializerToStaticConstructor(0, field);
2145 override public void LeaveGenericReferenceExpression(GenericReferenceExpression node)
2147 if (node.Target.Entity == null || TypeSystemServices.IsError(node.Target.Entity))
2149 BindExpressionType(node, TypeSystemServices.ErrorEntity);
2150 return;
2153 IEntity entity = NameResolutionService.ResolveGenericReferenceExpression(node, node.Target.Entity);
2154 Bind(node, entity);
2156 if (node.Target.Entity.EntityType == EntityType.Type)
2158 BindTypeReferenceExpressionType(node, (IType)entity);
2160 else if (node.Target.Entity.EntityType == EntityType.Method)
2162 BindExpressionType(node, ((IMethod)entity).Type);
2166 override public void OnReferenceExpression(ReferenceExpression node)
2168 if (AlreadyBound(node)) return;
2170 IEntity entity = ResolveName(node, node.Name);
2171 if (null == entity)
2173 Error(node);
2174 return;
2177 // BOO-314 - if we are trying to invoke
2178 // something, let's make sure it is
2179 // something callable, otherwise, let's
2180 // try to find something callable
2181 if (AstUtil.IsTargetOfMethodInvocation(node)
2182 && !IsCallableEntity(entity))
2184 IEntity callable = ResolveCallable(node);
2185 if (null != callable) entity = callable;
2188 IMember member = entity as IMember;
2189 if (null != member)
2191 if (IsExtensionMethod(member))
2193 Bind(node, member);
2194 return;
2196 ResolveMemberInfo(node, member);
2197 return;
2200 EnsureRelatedNodeWasVisited(node, entity);
2201 node.Entity = entity;
2202 PostProcessReferenceExpression(node);
2205 private static bool AlreadyBound(ReferenceExpression node)
2207 return null != node.ExpressionType;
2210 private IEntity ResolveCallable(ReferenceExpression node)
2212 return NameResolutionService.Resolve(node.Name,
2213 EntityType.Type
2214 | EntityType.Method
2215 | EntityType.BuiltinFunction
2216 | EntityType.Event);
2219 private bool IsCallableEntity(IEntity entity)
2221 switch (entity.EntityType)
2223 case EntityType.Method:
2224 case EntityType.Type:
2225 case EntityType.Event:
2226 case EntityType.BuiltinFunction:
2227 case EntityType.Constructor:
2228 return true;
2230 case EntityType.Ambiguous:
2231 // let overload resolution deal with it
2232 return true;
2234 ITypedEntity typed = entity as ITypedEntity;
2235 return null == typed ? false : TypeSystemServices.IsCallable(typed.Type);
2238 void PostProcessReferenceExpression(ReferenceExpression node)
2240 IEntity tag = GetEntity(node);
2241 switch (tag.EntityType)
2243 case EntityType.Type:
2245 BindTypeReferenceExpressionType(node, (IType)tag);
2246 break;
2249 case EntityType.Ambiguous:
2251 tag = ResolveAmbiguousReference(node, (Ambiguous)tag);
2252 IMember resolvedMember = tag as IMember;
2253 if (null != resolvedMember)
2255 ResolveMemberInfo(node, resolvedMember);
2256 break;
2258 if (tag is IType)
2260 BindTypeReferenceExpressionType(node, (IType)tag);
2261 break;
2263 if (!AstUtil.IsTargetOfMethodInvocation(node)
2264 && !AstUtil.IsTargetOfSlicing(node)
2265 && !AstUtil.IsLhsOfAssignment(node))
2267 Error(node, CompilerErrorFactory.AmbiguousReference(
2268 node,
2269 node.Name,
2270 ((Ambiguous)tag).Entities));
2272 break;
2275 case EntityType.Namespace:
2277 if (IsStandaloneReference(node))
2279 Error(node, CompilerErrorFactory.NamespaceIsNotAnExpression(node, tag.Name));
2281 break;
2284 case EntityType.Parameter:
2285 case EntityType.Local:
2287 ILocalEntity local = (ILocalEntity)node.Entity;
2288 local.IsUsed = true;
2289 BindExpressionType(node, local.Type);
2290 break;
2293 default:
2295 if (EntityType.BuiltinFunction == tag.EntityType)
2297 CheckBuiltinUsage(node, tag);
2299 else
2301 if (node.ExpressionType == null)
2303 BindExpressionType(node, ((ITypedEntity)tag).Type);
2306 break;
2311 protected virtual void BindTypeReferenceExpressionType(Expression node, IType type)
2313 if (IsStandaloneReference(node))
2315 BindExpressionType(node, TypeSystemServices.TypeType);
2317 else
2319 BindExpressionType(node, type);
2323 protected virtual void CheckBuiltinUsage(ReferenceExpression node, IEntity entity)
2325 if (!AstUtil.IsTargetOfMethodInvocation(node))
2327 Error(node, CompilerErrorFactory.BuiltinCannotBeUsedAsExpression(node, entity.Name));
2331 override public bool EnterMemberReferenceExpression(MemberReferenceExpression node)
2333 return null == node.ExpressionType;
2336 INamespace GetReferenceNamespace(MemberReferenceExpression expression)
2338 Expression target = expression.Target;
2339 INamespace ns = target.ExpressionType;
2340 if (null != ns)
2342 return GetConcreteExpressionType(target);
2344 return (INamespace)GetEntity(target);
2347 protected virtual void LeaveExplodeExpression(UnaryExpression node)
2349 IType type = GetConcreteExpressionType(node.Operand);
2350 if (!type.IsArray)
2352 Error(CompilerErrorFactory.ExplodedExpressionMustBeArray(node));
2354 BindExpressionType(node, type);
2357 override public void LeaveMemberReferenceExpression(MemberReferenceExpression node)
2359 _context.TraceVerbose("LeaveMemberReferenceExpression: {0}", node);
2361 if (TypeSystemServices.IsError(node.Target))
2363 Error(node);
2365 else
2367 ProcessMemberReferenceExpression(node);
2371 virtual protected void MemberNotFound(MemberReferenceExpression node, INamespace ns)
2373 EntityType et = (!AstUtil.IsTargetOfMethodInvocation(node)) ? EntityType.Any : EntityType.Method;
2374 Error(node,
2375 CompilerErrorFactory.MemberNotFound(node,
2376 (((IEntity)ns).ToString()),
2377 NameResolutionService.GetMostSimilarMemberName(ns, node.Name, et)));
2380 virtual protected bool ShouldRebindMember(IEntity entity)
2382 return entity == null;
2385 IEntity ResolveMember(MemberReferenceExpression node)
2387 IEntity member = node.Entity;
2388 if (!ShouldRebindMember(member)) return member;
2390 INamespace ns = GetReferenceNamespace(node);
2391 member = NameResolutionService.Resolve(ns, node.Name);
2392 if (null != member)
2394 IAccessibleMember accessible = member as IAccessibleMember;
2395 if (null != accessible && !IsAccessible(accessible))
2397 IEntity extension = NameResolutionService.ResolveExtension(ns, node.Name);
2398 if (null != extension) return extension;
2400 return member;
2403 member = NameResolutionService.ResolveExtension(ns, node.Name);
2404 if (null == member) MemberNotFound(node, ns);
2406 return member;
2409 virtual protected void ProcessMemberReferenceExpression(MemberReferenceExpression node)
2411 IEntity member = ResolveMember(node);
2412 if (null == member) return;
2414 if (EntityType.Ambiguous == member.EntityType)
2416 member = ResolveAmbiguousReference(node, (Ambiguous)member);
2419 EnsureRelatedNodeWasVisited(node, member);
2421 if (EntityType.Namespace == member.EntityType)
2423 string ns = null;
2424 foreach (Import import in _currentModule.Imports)
2426 if (import.NamespaceUsed) continue;
2427 if (null == ns) ns = node.ToCodeString();
2428 if (import.Namespace == ns)
2430 import.NamespaceUsed = true;
2431 break;
2436 IMember memberInfo = member as IMember;
2437 if (null != memberInfo)
2439 if (!AssertTargetContext(node, memberInfo))
2441 Error(node);
2442 return;
2445 if (EntityType.Method != memberInfo.EntityType)
2447 BindExpressionType(node, GetInferredType(memberInfo));
2449 else
2451 BindExpressionType(node, memberInfo.Type);
2455 if (EntityType.Property == member.EntityType)
2457 IProperty property = (IProperty)member;
2458 if (IsIndexedProperty(property))
2460 if (!AstUtil.IsTargetOfSlicing(node)
2461 && (!property.IsExtension || property.GetParameters().Length > 1))
2463 Error(node, CompilerErrorFactory.PropertyRequiresParameters(
2464 AstUtil.GetMemberAnchor(node),
2465 member.FullName));
2466 return;
2469 if (IsWriteOnlyProperty(property) && !IsBeingAssignedTo(node))
2471 Error(node, CompilerErrorFactory.PropertyIsWriteOnly(
2472 AstUtil.GetMemberAnchor(node),
2473 member.FullName));
2476 else if (EntityType.Event == member.EntityType)
2478 if (!AstUtil.IsTargetOfMethodInvocation(node) &&
2479 !AstUtil.IsLhsOfInPlaceAddSubtract(node))
2481 if (CurrentType == memberInfo.DeclaringType)
2483 InternalEvent ev = (InternalEvent)member;
2484 node.Name = ev.BackingField.Name;
2485 node.Entity = ev.BackingField;
2486 BindExpressionType(node, ev.BackingField.Type);
2487 return;
2489 else
2491 Error(node,
2492 CompilerErrorFactory.EventIsNotAnExpression(node,
2493 member.FullName));
2498 Bind(node, member);
2499 PostProcessReferenceExpression(node);
2502 private bool IsBeingAssignedTo(MemberReferenceExpression node)
2504 Node current = node;
2505 Node parent = current.ParentNode;
2506 while (!(parent is BinaryExpression))
2508 current = parent;
2509 parent = parent.ParentNode;
2510 if (parent == null || !(parent is Expression)) return false;
2512 return ((BinaryExpression)parent).Left == current;
2515 private bool IsWriteOnlyProperty(IProperty property)
2517 return null == property.GetGetMethod();
2520 private IEntity ResolveAmbiguousLValue(Expression sourceNode, Ambiguous candidates, Expression rvalue)
2522 if (!candidates.AllEntitiesAre(EntityType.Property)) return null;
2524 IEntity[] entities = candidates.Entities;
2525 IEntity[] getters = GetSetMethods(entities);
2526 ExpressionCollection args = new ExpressionCollection();
2527 args.Add(rvalue);
2528 IEntity found = GetCorrectCallableReference(sourceNode, args, getters);
2529 if (null != found && EntityType.Method == found.EntityType)
2531 IProperty property = (IProperty)entities[GetIndex(getters, found)];
2532 BindProperty(sourceNode, property);
2533 return property;
2535 return null;
2538 private static void BindProperty(Expression expression, IProperty property)
2540 expression.Entity = property;
2541 expression.ExpressionType = property.Type;
2544 private IEntity ResolveAmbiguousReference(ReferenceExpression node, Ambiguous candidates)
2546 if (!AstUtil.IsTargetOfSlicing(node)
2547 && !AstUtil.IsLhsOfAssignment(node))
2549 if (candidates.AllEntitiesAre(EntityType.Property))
2551 return ResolveAmbiguousPropertyReference(node, candidates, EmptyExpressionCollection);
2553 else if (candidates.AllEntitiesAre(EntityType.Method))
2555 return ResolveAmbiguousMethodReference(node, candidates, EmptyExpressionCollection);
2557 else if (candidates.AllEntitiesAre(EntityType.Type))
2559 return ResolveAmbiguousTypeReference(node, candidates);
2563 return ResolveAmbiguousReferenceByAccessibility(candidates);
2566 private IEntity ResolveAmbiguousMethodReference(ReferenceExpression node, Ambiguous candidates, ExpressionCollection args)
2568 //BOO-656
2569 if (!AstUtil.IsTargetOfMethodInvocation(node)
2570 && !AstUtil.IsTargetOfSlicing(node)
2571 && !AstUtil.IsLhsOfAssignment(node))
2573 return candidates.Entities[0];
2575 return candidates;
2578 private IEntity ResolveAmbiguousPropertyReference(ReferenceExpression node, Ambiguous candidates, ExpressionCollection args)
2580 IEntity[] entities = candidates.Entities;
2581 IEntity[] getters = GetGetMethods(entities);
2582 IEntity found = GetCorrectCallableReference(node, args, getters);
2583 if (null != found && EntityType.Method == found.EntityType)
2585 IProperty property = (IProperty)entities[GetIndex(getters, found)];
2586 BindProperty(node, property);
2587 return property;
2589 return candidates;
2592 private IEntity ResolveAmbiguousTypeReference(ReferenceExpression node, Ambiguous candidates)
2594 bool isGenericReference = (node.ParentNode is GenericReferenceExpression);
2596 List matches = new List();
2598 foreach (IEntity candidate in candidates.Entities)
2600 IType type = candidate as IType;
2601 bool isGenericType = (type != null && type.GenericInfo != null);
2602 if (isGenericType == isGenericReference)
2604 matches.Add(candidate);
2608 if (matches.Count == 1)
2610 Bind(node, (IEntity)matches[0]);
2612 else
2614 Bind(node, new Ambiguous(matches));
2617 return node.Entity;
2620 private IEntity ResolveAmbiguousReferenceByAccessibility(Ambiguous candidates)
2622 List newEntities = new List();
2623 foreach (IEntity entity in candidates.Entities)
2625 if (!IsInaccessible(entity))
2626 { newEntities.Add(entity); }
2629 if (newEntities.Count == 1)
2630 { return (IEntity)newEntities[0]; }
2632 return new Ambiguous(newEntities);
2635 private int GetIndex(IEntity[] entities, IEntity entity)
2637 for (int i=0; i<entities.Length; ++i)
2639 if (entities[i] == entity) return i;
2641 throw new ArgumentException("entity");
2644 override public void LeaveUnlessStatement(UnlessStatement node)
2646 node.Condition = AssertBoolContext(node.Condition);
2649 override public void LeaveIfStatement(IfStatement node)
2651 node.Condition = AssertBoolContext(node.Condition);
2654 override public void LeaveConditionalExpression(ConditionalExpression node)
2656 node.Condition = AssertBoolContext(node.Condition);
2658 IType trueType = GetExpressionType(node.TrueValue);
2659 IType falseType = GetExpressionType(node.FalseValue);
2661 BindExpressionType(node, GetMostGenericType(trueType, falseType));
2664 override public bool EnterWhileStatement(WhileStatement node)
2666 return true;
2669 override public void LeaveWhileStatement(WhileStatement node)
2671 node.Condition = AssertBoolContext(node.Condition);
2674 override public void LeaveYieldStatement(YieldStatement node)
2676 if (EntityType.Constructor == _currentMethod.EntityType)
2678 Error(CompilerErrorFactory.YieldInsideConstructor(node));
2680 else
2682 _currentMethod.AddYieldStatement(node);
2686 override public void LeaveReturnStatement(ReturnStatement node)
2688 if (null == node.Expression) return;
2690 // forces anonymous types to be correctly
2691 // instantiated
2692 IType expressionType = GetConcreteExpressionType(node.Expression);
2693 if (TypeSystemServices.VoidType == expressionType
2694 && node.ContainsAnnotation(OptionalReturnStatementAnnotation))
2696 node.ParentNode.Replace(
2697 node,
2698 new ExpressionStatement(node.Expression));
2699 return;
2702 IType returnType = _currentMethod.ReturnType;
2703 if (TypeSystemServices.IsUnknown(returnType))
2705 _currentMethod.AddReturnExpression(node.Expression);
2707 else
2709 AssertTypeCompatibility(node.Expression, returnType, expressionType);
2713 protected Expression GetCorrectIterator(Expression iterator)
2715 IType type = GetExpressionType(iterator);
2716 if (TypeSystemServices.IsError(type))
2718 return iterator;
2721 if (!TypeSystemServices.IEnumerableType.IsAssignableFrom(type) &&
2722 !TypeSystemServices.IEnumeratorType.IsAssignableFrom(type))
2724 if (IsRuntimeIterator(type))
2726 if (IsTextReader(type))
2728 return CodeBuilder.CreateMethodInvocation(TextReaderEnumerator_lines, iterator);
2730 else
2732 return CodeBuilder.CreateMethodInvocation(RuntimeServices_GetEnumerable, iterator);
2735 else
2737 IMethod method = ResolveGetEnumerator(iterator, type);
2738 if (null == method)
2740 Error(CompilerErrorFactory.InvalidIteratorType(iterator, type.ToString()));
2742 else
2744 return CodeBuilder.CreateMethodInvocation(iterator, method);
2748 return iterator;
2751 IMethod ResolveGetEnumerator(Node sourceNode, IType type)
2753 IMethod method = ResolveMethod(type, "GetEnumerator");
2754 if (null != method)
2756 EnsureRelatedNodeWasVisited(sourceNode, method);
2757 if (0 == method.GetParameters().Length &&
2758 method.ReturnType.IsSubclassOf(TypeSystemServices.IEnumeratorType))
2760 return method;
2763 return null;
2766 /// <summary>
2767 /// Process a iterator and its declarations and returns a new iterator
2768 /// expression if necessary.
2769 /// </summary>
2770 protected Expression ProcessIterator(Expression iterator, DeclarationCollection declarations)
2772 iterator = GetCorrectIterator(iterator);
2773 ProcessDeclarationsForIterator(declarations, GetExpressionType(iterator));
2774 return iterator;
2777 public override void OnGotoStatement(GotoStatement node)
2779 // don't try to resolve label references
2782 override public void OnForStatement(ForStatement node)
2784 Visit(node.Iterator);
2785 node.Iterator = ProcessIterator(node.Iterator, node.Declarations);
2786 VisitForStatementBlock(node);
2789 protected void VisitForStatementBlock(ForStatement node)
2791 EnterForNamespace(node);
2792 Visit(node.Block);
2793 Visit(node.OrBlock);
2794 Visit(node.ThenBlock);
2795 LeaveNamespace();
2798 private void EnterForNamespace(ForStatement node)
2800 EnterNamespace(new DeclarationsNamespace(CurrentNamespace, TypeSystemServices, node.Declarations));
2803 override public void OnUnpackStatement(UnpackStatement node)
2805 Visit(node.Expression);
2807 node.Expression = GetCorrectIterator(node.Expression);
2809 IType defaultDeclarationType = GetEnumeratorItemType(GetExpressionType(node.Expression));
2810 foreach (Declaration d in node.Declarations)
2812 bool declareNewVariable = d.Type != null;
2814 GetDeclarationType(defaultDeclarationType, d);
2815 if (declareNewVariable)
2817 AssertUniqueLocal(d);
2819 else
2821 IEntity tag = NameResolutionService.Resolve(d.Name);
2822 if (null != tag)
2824 Bind(d, tag);
2825 AssertLValue(d);
2826 continue;
2829 DeclareLocal(d, false);
2833 override public void LeaveRaiseStatement(RaiseStatement node)
2835 if (node.Exception == null) return;
2837 IType exceptionType = GetExpressionType(node.Exception);
2838 if (TypeSystemServices.StringType == exceptionType)
2840 node.Exception = CodeBuilder.CreateConstructorInvocation(
2841 node.Exception.LexicalInfo,
2842 Exception_StringConstructor,
2843 node.Exception);
2845 else if (!TypeSystemServices.ExceptionType.IsAssignableFrom(exceptionType))
2847 Error(CompilerErrorFactory.InvalidRaiseArgument(node.Exception,
2848 exceptionType.ToString()));
2852 override public void OnExceptionHandler(ExceptionHandler node)
2854 bool untypedException = (node.Flags & ExceptionHandlerFlags.Untyped) == ExceptionHandlerFlags.Untyped;
2855 bool anonymousException = (node.Flags & ExceptionHandlerFlags.Anonymous) == ExceptionHandlerFlags.Anonymous;
2856 bool filterHandler = (node.Flags & ExceptionHandlerFlags.Filter) == ExceptionHandlerFlags.Filter;
2858 if (untypedException)
2860 // If untyped, set the handler to except System.Exception
2861 node.Declaration.Type = CodeBuilder.CreateTypeReference(TypeSystemServices.ExceptionType);
2863 else
2865 Visit(node.Declaration.Type);
2867 // Require typed exception handlers to except only
2868 // exceptions at least as derived as System.Exception
2869 if(!TypeSystemServices.ExceptionType.IsAssignableFrom(GetType(node.Declaration.Type)))
2871 Errors.Add(CompilerErrorFactory.InvalidExceptArgument(node.Declaration.Type, GetType(node.Declaration.Type).FullName));
2875 if(!anonymousException)
2877 // If the exception is not anonymous, place it into a
2878 // local variable and enter a new namespace
2879 node.Declaration.Entity = DeclareLocal(node.Declaration, node.Declaration.Name, GetType(node.Declaration.Type), true);
2880 EnterNamespace(new DeclarationsNamespace(CurrentNamespace, TypeSystemServices, node.Declaration));
2885 // The filter handler has access to the exception if it
2886 // is not anonymous, so it is protected to ensure
2887 // any exception in the filter condition (a big no-no)
2888 // will still clean up the namespace if necessary
2889 if (filterHandler)
2891 Visit(node.FilterCondition);
2894 Visit(node.Block);
2896 finally
2898 // Clean up the namespace if necessary
2899 if(!anonymousException)
2901 LeaveNamespace();
2906 protected virtual bool IsValidIncrementDecrementOperand(Expression e)
2908 IType type = GetExpressionType(e);
2909 return IsNumber(type) || TypeSystemServices.IsDuckType(type);
2912 void LeaveIncrementDecrement(UnaryExpression node)
2914 if (AssertLValue(node.Operand))
2916 if (!IsValidIncrementDecrementOperand(node.Operand))
2918 InvalidOperatorForType(node);
2920 else
2922 ExpandIncrementDecrement(node);
2925 else
2927 Error(node);
2931 void ExpandIncrementDecrement(UnaryExpression node)
2933 Node expansion = null;
2934 if (IsArraySlicing(node.Operand))
2936 expansion = ExpandIncrementDecrementArraySlicing(node);
2938 else
2940 expansion = ExpandSimpleIncrementDecrement(node);
2942 node.ParentNode.Replace(node, expansion);
2943 Visit(expansion);
2946 Expression ExpandIncrementDecrementArraySlicing(UnaryExpression node)
2948 SlicingExpression slicing = (SlicingExpression)node.Operand;
2949 CheckNoComplexSlicing(slicing);
2950 Visit(slicing);
2951 return CreateSideEffectAwareSlicingOperation(
2952 node.LexicalInfo,
2953 GetEquivalentBinaryOperator(node.Operator),
2954 slicing,
2955 CodeBuilder.CreateIntegerLiteral(1),
2956 DeclareOldValueTempIfNeeded(node));
2959 private Expression CreateSideEffectAwareSlicingOperation(LexicalInfo lexicalInfo, BinaryOperatorType binaryOperator, SlicingExpression lvalue, Expression rvalue, InternalLocal returnValue)
2961 MethodInvocationExpression eval = CodeBuilder.CreateEvalInvocation(lexicalInfo);
2962 if (HasSideEffect(lvalue.Target))
2964 InternalLocal temp = AddInitializedTempLocal(eval, lvalue.Target);
2965 lvalue.Target = CodeBuilder.CreateReference(temp);
2968 foreach (Slice slice in lvalue.Indices)
2970 Expression index = slice.Begin;
2971 if (HasSideEffect(index))
2973 InternalLocal temp = AddInitializedTempLocal(eval, index);
2974 slice.Begin = CodeBuilder.CreateReference(temp);
2978 BinaryExpression addition = CodeBuilder.CreateBoundBinaryExpression(
2979 GetExpressionType(lvalue),
2980 binaryOperator,
2981 CloneOrAssignToTemp(returnValue, lvalue),
2982 rvalue);
2983 Expression expansion = CodeBuilder.CreateAssignment(
2984 lvalue.CloneNode(),
2985 addition);
2986 // Resolve operator overloads if any
2987 BindArithmeticOperator(addition);
2988 if (eval.Arguments.Count > 0 || null != returnValue)
2990 eval.Arguments.Add(expansion);
2991 if (null != returnValue)
2993 eval.Arguments.Add(CodeBuilder.CreateReference(returnValue));
2995 BindExpressionType(eval, GetExpressionType(lvalue));
2996 expansion = eval;
2998 return expansion;
3001 InternalLocal AddInitializedTempLocal(MethodInvocationExpression eval, Expression initializer)
3003 InternalLocal temp = DeclareTempLocal(GetExpressionType(initializer));
3004 eval.Arguments.Add(
3005 CodeBuilder.CreateAssignment(
3006 CodeBuilder.CreateReference(temp),
3007 initializer));
3008 return temp;
3011 InternalLocal DeclareOldValueTempIfNeeded(UnaryExpression node)
3013 return AstUtil.IsPostUnaryOperator(node.Operator)
3014 ? DeclareTempLocal(GetExpressionType(node.Operand))
3015 : null;
3018 Expression ExpandSimpleIncrementDecrement(UnaryExpression node)
3020 InternalLocal oldValue = DeclareOldValueTempIfNeeded(node);
3022 BinaryExpression addition = CodeBuilder.CreateBoundBinaryExpression(
3023 GetExpressionType(node.Operand),
3024 GetEquivalentBinaryOperator(node.Operator),
3025 CloneOrAssignToTemp(oldValue, node.Operand),
3026 CodeBuilder.CreateIntegerLiteral(1));
3028 BinaryExpression assign = CodeBuilder.CreateAssignment(
3029 node.LexicalInfo,
3030 node.Operand,
3031 addition);
3033 // Resolve operator overloads if any
3034 BindArithmeticOperator(addition);
3036 return null == oldValue
3037 ? (Expression) assign
3038 : CodeBuilder.CreateEvalInvocation(
3039 node.LexicalInfo,
3040 assign,
3041 CodeBuilder.CreateReference(oldValue));
3044 Expression CloneOrAssignToTemp(InternalLocal temp, Expression operand)
3046 return null == temp
3047 ? operand.CloneNode()
3048 : CodeBuilder.CreateAssignment(
3049 CodeBuilder.CreateReference(temp),
3050 operand.CloneNode());
3053 BinaryOperatorType GetEquivalentBinaryOperator(UnaryOperatorType op)
3055 return op == UnaryOperatorType.Increment || op == UnaryOperatorType.PostIncrement
3056 ? BinaryOperatorType.Addition
3057 : BinaryOperatorType.Subtraction;
3060 UnaryOperatorType GetRelatedPreOperator(UnaryOperatorType op)
3062 switch (op)
3064 case UnaryOperatorType.PostIncrement:
3066 return UnaryOperatorType.Increment;
3068 case UnaryOperatorType.PostDecrement:
3070 return UnaryOperatorType.Decrement;
3073 throw new ArgumentException("op");
3076 override public bool EnterUnaryExpression(UnaryExpression node)
3078 if (AstUtil.IsPostUnaryOperator(node.Operator))
3080 if (NodeType.ExpressionStatement == node.ParentNode.NodeType)
3082 // nothing to do, a post operator inside a statement
3083 // behaves just like its equivalent pre operator
3084 node.Operator = GetRelatedPreOperator(node.Operator);
3087 return true;
3090 override public void LeaveUnaryExpression(UnaryExpression node)
3092 switch (node.Operator)
3094 case UnaryOperatorType.Explode:
3096 LeaveExplodeExpression(node);
3097 break;
3099 case UnaryOperatorType.LogicalNot:
3101 LeaveLogicalNot(node);
3102 break;
3105 case UnaryOperatorType.Increment:
3106 case UnaryOperatorType.PostIncrement:
3107 case UnaryOperatorType.Decrement:
3108 case UnaryOperatorType.PostDecrement:
3110 LeaveIncrementDecrement(node);
3111 break;
3114 case UnaryOperatorType.UnaryNegation:
3116 LeaveUnaryNegation(node);
3117 break;
3120 case UnaryOperatorType.OnesComplement:
3122 LeaveOnesComplement(node);
3123 break;
3126 default:
3128 NotImplemented(node, "unary operator not supported");
3129 break;
3134 private void LeaveOnesComplement(UnaryExpression node)
3136 if (IsPrimitiveOnesComplementOperand(node.Operand))
3138 BindExpressionType(node, GetExpressionType(node.Operand));
3140 else
3142 ProcessOperatorOverload(node);
3146 private bool IsPrimitiveOnesComplementOperand(Expression operand)
3148 IType type = GetExpressionType(operand);
3149 return TypeSystemServices.IsIntegerNumber(type) || type.IsEnum;
3152 private void LeaveLogicalNot(UnaryExpression node)
3154 node.Operand = AssertBoolContext(node.Operand);
3155 BindExpressionType(node, TypeSystemServices.BoolType);
3158 private void LeaveUnaryNegation(UnaryExpression node)
3160 if (IsPrimitiveNumber(node.Operand))
3162 BindExpressionType(node, GetExpressionType(node.Operand));
3164 else
3166 ProcessOperatorOverload(node);
3170 private void ProcessOperatorOverload(UnaryExpression node)
3172 if (! ResolveOperator(node))
3174 InvalidOperatorForType(node);
3178 override public bool EnterBinaryExpression(BinaryExpression node)
3180 if (BinaryOperatorType.Assign == node.Operator)
3182 if (NodeType.ReferenceExpression == node.Left.NodeType &&
3183 null == node.Left.Entity)
3185 // Auto local declaration:
3186 // assign to unknown reference implies local
3187 // declaration
3188 ReferenceExpression reference = (ReferenceExpression)node.Left;
3189 IEntity info = NameResolutionService.Resolve(reference.Name);
3190 if (null == info || TypeSystemServices.IsBuiltin(info) || IsInaccessible(info))
3192 Visit(node.Right);
3193 IType expressionType = MapNullToObject(GetConcreteExpressionType(node.Right));
3194 IEntity local = DeclareLocal(reference, reference.Name, expressionType);
3195 reference.Entity = local;
3196 BindExpressionType(node.Left, expressionType);
3197 BindExpressionType(node, expressionType);
3198 return false;
3202 return true;
3205 bool IsInaccessible(IEntity info)
3207 IAccessibleMember accessible = info as IAccessibleMember;
3208 if (accessible != null && accessible.IsPrivate
3209 && accessible.DeclaringType != CurrentType)
3211 return true;
3213 return false;
3216 override public void LeaveBinaryExpression(BinaryExpression node)
3218 if (TypeSystemServices.IsUnknown(node.Left) ||
3219 TypeSystemServices.IsUnknown(node.Right))
3221 BindExpressionType(node, Unknown.Default);
3222 return;
3225 if (TypeSystemServices.IsError(node.Left)
3226 || TypeSystemServices.IsError(node.Right))
3228 Error(node);
3229 return;
3231 BindBinaryExpression(node);
3234 protected virtual void BindBinaryExpression(BinaryExpression node)
3236 if (IsEnumOperation(node))
3238 BindEnumOperation(node);
3239 return;
3242 switch (node.Operator)
3244 case BinaryOperatorType.Assign:
3246 BindAssignment(node);
3247 break;
3250 case BinaryOperatorType.Addition:
3252 if (GetExpressionType(node.Left).IsArray &&
3253 GetExpressionType(node.Right).IsArray)
3255 BindArrayAddition(node);
3257 else
3259 BindArithmeticOperator(node);
3261 break;
3264 case BinaryOperatorType.Subtraction:
3265 case BinaryOperatorType.Multiply:
3266 case BinaryOperatorType.Division:
3267 case BinaryOperatorType.Modulus:
3268 case BinaryOperatorType.Exponentiation:
3270 BindArithmeticOperator(node);
3271 break;
3274 case BinaryOperatorType.TypeTest:
3276 BindTypeTest(node);
3277 break;
3280 case BinaryOperatorType.ReferenceEquality:
3282 BindReferenceEquality(node);
3283 break;
3286 case BinaryOperatorType.ReferenceInequality:
3288 BindReferenceEquality(node);
3289 break;
3292 case BinaryOperatorType.Or:
3293 case BinaryOperatorType.And:
3295 BindLogicalOperator(node);
3296 break;
3299 case BinaryOperatorType.BitwiseAnd:
3300 case BinaryOperatorType.BitwiseOr:
3301 case BinaryOperatorType.ExclusiveOr:
3302 case BinaryOperatorType.ShiftLeft:
3303 case BinaryOperatorType.ShiftRight:
3305 BindBitwiseOperator(node);
3306 break;
3309 case BinaryOperatorType.InPlaceSubtraction:
3310 case BinaryOperatorType.InPlaceAddition:
3312 BindInPlaceAddSubtract(node);
3313 break;
3316 case BinaryOperatorType.InPlaceShiftLeft:
3317 case BinaryOperatorType.InPlaceShiftRight:
3318 case BinaryOperatorType.InPlaceDivision:
3319 case BinaryOperatorType.InPlaceMultiply:
3320 case BinaryOperatorType.InPlaceBitwiseOr:
3321 case BinaryOperatorType.InPlaceBitwiseAnd:
3322 case BinaryOperatorType.InPlaceExclusiveOr:
3324 BindInPlaceArithmeticOperator(node);
3325 break;
3328 case BinaryOperatorType.GreaterThan:
3329 case BinaryOperatorType.GreaterThanOrEqual:
3330 case BinaryOperatorType.LessThan:
3331 case BinaryOperatorType.LessThanOrEqual:
3332 case BinaryOperatorType.Inequality:
3333 case BinaryOperatorType.Equality:
3335 BindCmpOperator(node);
3336 break;
3339 default:
3341 if (!ResolveOperator(node))
3343 InvalidOperatorForTypes(node);
3345 break;
3350 IType GetMostGenericType(BinaryExpression node)
3352 return GetMostGenericType(
3353 GetExpressionType(node.Left),
3354 GetExpressionType(node.Right));
3357 bool IsNullableOperation(BinaryExpression node)
3359 if (null == node.Left.ExpressionType || null == node.Right.ExpressionType)
3361 return false;
3364 return TypeSystemServices.IsNullable(GetExpressionType(node.Left))
3365 || TypeSystemServices.IsNullable(GetExpressionType(node.Right));
3368 bool IsEnumOperation(BinaryExpression node)
3370 switch (node.Operator)
3372 case BinaryOperatorType.Addition:
3373 case BinaryOperatorType.Subtraction:
3374 case BinaryOperatorType.BitwiseAnd:
3375 case BinaryOperatorType.BitwiseOr:
3376 case BinaryOperatorType.ExclusiveOr:
3377 IType lhs = GetExpressionType(node.Left);
3378 IType rhs = GetExpressionType(node.Right);
3379 if (lhs.IsEnum) return IsValidEnumOperand(lhs, rhs);
3380 if (rhs.IsEnum) return IsValidEnumOperand(rhs, lhs);
3381 break;
3383 return false;
3386 bool IsValidEnumOperand(IType expected, IType actual)
3388 if (expected == actual) return true;
3389 if (actual.IsEnum) return true;
3390 return TypeSystemServices.IsIntegerNumber(actual);
3393 void BindEnumOperation(BinaryExpression node)
3395 IType lhs = GetExpressionType(node.Left);
3396 IType rhs = GetExpressionType(node.Right);
3397 switch(node.Operator)
3399 case BinaryOperatorType.Addition:
3400 if (lhs.IsEnum != rhs.IsEnum)
3402 BindExpressionType(node, lhs.IsEnum ? lhs : rhs);
3403 return;
3405 break;
3406 case BinaryOperatorType.Subtraction:
3407 if (lhs == rhs)
3409 BindExpressionType(node, TypeSystemServices.IntType);
3410 return;
3412 else if (lhs.IsEnum && !rhs.IsEnum)
3414 BindExpressionType(node, lhs);
3415 return;
3417 break;
3418 case BinaryOperatorType.BitwiseAnd:
3419 case BinaryOperatorType.BitwiseOr:
3420 case BinaryOperatorType.ExclusiveOr:
3421 if (lhs == rhs)
3423 BindExpressionType(node, lhs);
3424 return;
3426 break;
3428 if (!ResolveOperator(node))
3430 InvalidOperatorForTypes(node);
3434 void BindBitwiseOperator(BinaryExpression node)
3436 IType lhs = GetExpressionType(node.Left);
3437 IType rhs = GetExpressionType(node.Right);
3439 if (TypeSystemServices.IsIntegerOrBool(lhs) &&
3440 TypeSystemServices.IsIntegerOrBool(rhs))
3442 BindExpressionType(node, TypeSystemServices.GetPromotedNumberType(lhs, rhs));
3444 else
3446 // if (lhs.IsEnum && rhs == lhs)
3447 // {
3448 // BindExpressionType(node, lhs);
3449 // }
3450 // else
3451 // {
3452 if (!ResolveOperator(node))
3454 InvalidOperatorForTypes(node);
3456 // }
3460 bool IsChar(IType type)
3462 return TypeSystemServices.CharType == type;
3465 void BindCmpOperator(BinaryExpression node)
3467 if (BindNullableOperation(node))
3469 return;
3472 IType lhs = GetExpressionType(node.Left);
3473 IType rhs = GetExpressionType(node.Right);
3475 if (IsPrimitiveComparison(lhs, rhs))
3477 BindExpressionType(node, TypeSystemServices.BoolType);
3478 return;
3481 if (lhs.IsEnum || rhs.IsEnum)
3483 if (lhs == rhs || IsPrimitiveNumber(rhs) || IsPrimitiveNumber(lhs))
3485 BindExpressionType(node, TypeSystemServices.BoolType);
3487 else
3489 if (!ResolveOperator(node))
3491 InvalidOperatorForTypes(node);
3494 return;
3497 if (!ResolveOperator(node))
3499 switch (node.Operator)
3501 case BinaryOperatorType.Equality:
3503 if (OptimizeNullComparisons
3504 && (IsNull(node.Left) || IsNull(node.Right)))
3506 node.Operator = BinaryOperatorType.ReferenceEquality;
3507 BindReferenceEquality(node);
3508 break;
3510 Expression expression = CreateEquals(node);
3511 node.ParentNode.Replace(node, expression);
3512 break;
3515 case BinaryOperatorType.Inequality:
3517 if (OptimizeNullComparisons
3518 && (IsNull(node.Left) || IsNull(node.Right)))
3520 node.Operator = BinaryOperatorType.ReferenceInequality;
3521 BindReferenceEquality(node);
3522 break;
3524 Expression expression = CreateEquals(node);
3525 Node parent = node.ParentNode;
3526 parent.Replace(node, CodeBuilder.CreateNotExpression(expression));
3527 break;
3530 default:
3532 InvalidOperatorForTypes(node);
3533 break;
3539 private bool IsPrimitiveComparison(IType lhs, IType rhs)
3541 if (IsPrimitiveNumberOrChar(lhs) && IsPrimitiveNumberOrChar(rhs)) return true;
3542 if (IsBool(lhs) && IsBool(rhs)) return true;
3543 return false;
3546 private bool IsPrimitiveNumberOrChar(IType lhs)
3548 return IsPrimitiveNumber(lhs) || IsChar(lhs);
3551 private bool IsBool(IType lhs)
3553 return TypeSystemServices.BoolType == lhs;
3556 static bool IsNull(Expression node)
3558 return NodeType.NullLiteralExpression == node.NodeType;
3561 void BindLogicalOperator(BinaryExpression node)
3563 node.Left = AssertBoolContext(node.Left);
3564 node.Right = AssertBoolContext(node.Right);
3565 BindExpressionType(node, GetMostGenericType(node));
3568 void BindInPlaceAddSubtract(BinaryExpression node)
3570 IEntity entity = node.Left.Entity;
3571 if (null != entity &&
3572 (EntityType.Event == entity.EntityType
3573 || EntityType.Ambiguous == entity.EntityType))
3575 BindEventSubscription(node);
3577 else
3579 BindInPlaceArithmeticOperator(node);
3583 void BindEventSubscription(BinaryExpression node)
3585 IEntity tag = GetEntity(node.Left);
3586 if (EntityType.Event != tag.EntityType)
3588 if (EntityType.Ambiguous == tag.EntityType)
3590 IList found = ((Ambiguous)tag).Select(IsPublicEvent);
3591 if (found.Count != 1)
3593 tag = null;
3595 else
3597 tag = (IEntity)found[0];
3598 Bind(node.Left, tag);
3603 IEvent eventInfo = (IEvent)tag;
3604 IType rtype = GetExpressionType(node.Right);
3605 if (!AssertDelegateArgument(node, eventInfo, rtype))
3607 Error(node);
3608 return;
3611 IMethod method = null;
3612 if (node.Operator == BinaryOperatorType.InPlaceAddition)
3614 method = eventInfo.GetAddMethod();
3616 else
3618 method = eventInfo.GetRemoveMethod();
3619 CallableSignature expected = GetCallableSignature(eventInfo.Type);
3620 CallableSignature actual = GetCallableSignature(node.Right);
3621 if (expected != actual)
3623 Warnings.Add(
3624 CompilerWarningFactory.InvalidEventUnsubscribe(
3625 node,
3626 eventInfo.FullName,
3627 expected));
3631 MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation(
3632 ((MemberReferenceExpression)node.Left).Target,
3633 method,
3634 node.Right);
3635 node.ParentNode.Replace(node, mie);
3638 CallableSignature GetCallableSignature(Expression node)
3640 return GetCallableSignature(GetExpressionType(node));
3643 CallableSignature GetCallableSignature(IType type)
3645 return ((ICallableType)type).GetSignature();
3648 virtual protected void ProcessBuiltinInvocation(BuiltinFunction function, MethodInvocationExpression node)
3650 switch (function.FunctionType)
3652 case BuiltinFunctionType.Len:
3654 ProcessLenInvocation(node);
3655 break;
3658 case BuiltinFunctionType.AddressOf:
3660 ProcessAddressOfInvocation(node);
3661 break;
3664 case BuiltinFunctionType.Eval:
3666 ProcessEvalInvocation(node);
3667 break;
3670 default:
3672 NotImplemented(node, "BuiltinFunction: " + function);
3673 break;
3678 bool ProcessSwitchInvocation(MethodInvocationExpression node)
3680 if (BuiltinFunction.Switch != node.Target.Entity) return false;
3681 BindSwitchLabelReferences(node);
3682 if (CheckSwitchArguments(node)) return true;
3683 Error(node, CompilerErrorFactory.InvalidSwitch(node.Target));
3684 return true;
3687 private static void BindSwitchLabelReferences(MethodInvocationExpression node)
3689 for (int i = 1; i < node.Arguments.Count; ++i)
3691 ReferenceExpression label = (ReferenceExpression)node.Arguments[i];
3692 label.ExpressionType = Unknown.Default;
3696 bool CheckSwitchArguments(MethodInvocationExpression node)
3698 ExpressionCollection args = node.Arguments;
3699 if (args.Count > 1)
3701 Visit(args[0]);
3702 if (TypeSystemServices.IsIntegerNumber(GetExpressionType(args[0])))
3704 for (int i=1; i<args.Count; ++i)
3706 if (NodeType.ReferenceExpression != args[i].NodeType)
3708 return false;
3711 return true;
3714 return false;
3717 void ProcessEvalInvocation(MethodInvocationExpression node)
3719 if (node.Arguments.Count > 0)
3721 int allButLast = node.Arguments.Count-1;
3722 for (int i=0; i<allButLast; ++i)
3724 AssertHasSideEffect(node.Arguments[i]);
3726 BindExpressionType(node, GetConcreteExpressionType(node.Arguments[-1]));
3728 else
3730 BindExpressionType(node, TypeSystemServices.VoidType);
3734 void ProcessAddressOfInvocation(MethodInvocationExpression node)
3736 if (node.Arguments.Count != 1)
3738 Error(node, CompilerErrorFactory.MethodArgumentCount(node.Target, "__addressof__", 1));
3740 else
3742 Expression arg = node.Arguments[0];
3744 EntityType type = GetEntity(arg).EntityType;
3746 if (EntityType.Method != type)
3748 ReferenceExpression reference = arg as ReferenceExpression;
3749 if (null != reference && EntityType.Ambiguous == type)
3751 Error(node, CompilerErrorFactory.AmbiguousReference(arg, reference.Name, ((Ambiguous)arg.Entity).Entities));
3753 else
3755 Error(node, CompilerErrorFactory.MethodReferenceExpected(arg));
3758 else
3760 BindExpressionType(node, TypeSystemServices.IntPtrType);
3765 void ProcessLenInvocation(MethodInvocationExpression node)
3767 if ((node.Arguments.Count < 1) || (node.Arguments.Count > 2))
3769 Error(node, CompilerErrorFactory.MethodArgumentCount(node.Target, "len", node.Arguments.Count));
3770 return;
3773 MethodInvocationExpression resultingNode = null;
3775 Expression target = node.Arguments[0];
3776 IType type = GetExpressionType(target);
3777 bool isArray = TypeSystemServices.ArrayType.IsAssignableFrom(type);
3779 if ((!isArray) && (node.Arguments.Count != 1))
3781 Error(node, CompilerErrorFactory.MethodArgumentCount(node.Target, "len", node.Arguments.Count));
3783 if (TypeSystemServices.IsSystemObject(type))
3785 resultingNode = CodeBuilder.CreateMethodInvocation(RuntimeServices_Len, target);
3787 else if (TypeSystemServices.StringType == type)
3789 resultingNode = CodeBuilder.CreateMethodInvocation(target, String_get_Length);
3791 else if (isArray)
3793 if (node.Arguments.Count == 1)
3795 resultingNode = CodeBuilder.CreateMethodInvocation(target, Array_get_Length);
3797 else
3799 resultingNode = CodeBuilder.CreateMethodInvocation(target,
3800 Array_GetLength, node.Arguments[1]);
3803 else if (TypeSystemServices.ICollectionType.IsAssignableFrom(type))
3805 resultingNode = CodeBuilder.CreateMethodInvocation(target, ICollection_get_Count);
3807 else
3809 Error(CompilerErrorFactory.InvalidLen(target, type.ToString()));
3811 if (null != resultingNode)
3813 node.ParentNode.Replace(node, resultingNode);
3817 void CheckListLiteralArgumentInArrayConstructor(IType expectedElementType, MethodInvocationExpression constructor)
3819 ListLiteralExpression elements = constructor.Arguments[1] as ListLiteralExpression;
3820 if (null == elements) return;
3821 CheckItems(expectedElementType, elements.Items);
3824 private void CheckItems(IType expectedElementType, ExpressionCollection items)
3826 foreach (Expression element in items)
3828 AssertTypeCompatibility(element, expectedElementType, GetExpressionType(element));
3832 void ApplyBuiltinMethodTypeInference(MethodInvocationExpression expression, IMethod method)
3834 IType inferredType = null;
3836 if (Array_TypedEnumerableConstructor == method ||
3837 Array_TypedCollectionConstructor == method ||
3838 Array_TypedConstructor2 == method)
3840 IType type = TypeSystemServices.GetReferencedType(expression.Arguments[0]);
3841 if (null != type)
3843 if (Array_TypedCollectionConstructor == method)
3845 CheckListLiteralArgumentInArrayConstructor(type, expression);
3847 inferredType = TypeSystemServices.GetArrayType(type, 1);
3850 else if (MultiDimensionalArray_TypedConstructor == method)
3852 IType type = TypeSystemServices.GetReferencedType(expression.Arguments[0]);
3853 if (null != type)
3855 inferredType = TypeSystemServices.GetArrayType(type, expression.Arguments.Count-1);
3858 else if (Array_EnumerableConstructor == method)
3860 IType enumeratorItemType = GetEnumeratorItemType(GetExpressionType(expression.Arguments[0]));
3861 if (TypeSystemServices.ObjectType != enumeratorItemType)
3863 inferredType = TypeSystemServices.GetArrayType(enumeratorItemType, 1);
3864 expression.Target.Entity = Array_TypedEnumerableConstructor;
3865 expression.ExpressionType = Array_TypedEnumerableConstructor.ReturnType;
3866 expression.Arguments.Insert(0, CodeBuilder.CreateReference(enumeratorItemType));
3870 if (null != inferredType)
3872 Node parent = expression.ParentNode;
3873 parent.Replace(expression,
3874 CodeBuilder.CreateCast(inferredType, expression));
3878 protected virtual IEntity ResolveAmbiguousMethodInvocation(MethodInvocationExpression node, Ambiguous entity)
3880 _context.TraceVerbose("{0}: resolving ambigous method invocation: {1}", node.LexicalInfo, entity);
3882 IEntity resolved = ResolveCallableReference(node, entity);
3883 if (null != resolved) return resolved;
3885 if (TryToProcessAsExtensionInvocation(node)) return null;
3887 return CantResolveAmbiguousMethodInvocation(node, entity.Entities);
3890 private IEntity ResolveCallableReference(MethodInvocationExpression node, Ambiguous entity)
3892 IEntity resolved = _callableResolution.ResolveCallableReference(node.Arguments, entity.Entities);
3893 if (null == resolved) return null;
3895 IMember member = (IMember)resolved;
3896 if (NodeType.ReferenceExpression == node.Target.NodeType)
3898 ResolveMemberInfo((ReferenceExpression)node.Target, member);
3900 else
3902 Bind(node.Target, member);
3903 BindExpressionType(node.Target, member.Type);
3905 return resolved;
3908 private bool TryToProcessAsExtensionInvocation(MethodInvocationExpression node)
3910 IEntity extension = ResolveExtension(node);
3911 if (null == extension) return false;
3913 ProcessExtensionMethodInvocation(node, extension);
3914 return true;
3917 private IEntity ResolveExtension(MethodInvocationExpression node)
3919 MemberReferenceExpression mre = node.Target as MemberReferenceExpression;
3920 if (mre == null) return null;
3922 return NameResolutionService.ResolveExtension(GetReferenceNamespace(mre), mre.Name);
3925 protected virtual IEntity CantResolveAmbiguousMethodInvocation(MethodInvocationExpression node, IEntity[] entities)
3927 EmitCallableResolutionError(node, entities, node.Arguments);
3928 Error(node);
3929 return null;
3932 override public void OnMethodInvocationExpression(MethodInvocationExpression node)
3934 if (null != node.ExpressionType)
3936 _context.TraceVerbose("{0}: Method invocation already bound.", node.LexicalInfo);
3937 return;
3940 Visit(node.Target);
3942 if (ProcessSwitchInvocation(node)) return;
3944 if (ProcessMetaMethodInvocation(node)) return;
3946 Visit(node.Arguments);
3948 if (TypeSystemServices.IsError(node.Target)
3949 || TypeSystemServices.IsErrorAny(node.Arguments))
3951 Error(node);
3952 return;
3955 IEntity targetEntity = node.Target.Entity;
3956 if (null == targetEntity)
3958 ProcessGenericMethodInvocation(node);
3959 return;
3962 if (IsOrContainsBooExtensionMethod(targetEntity))
3964 ProcessExtensionMethodInvocation(node, targetEntity);
3965 return;
3968 ProcessMethodInvocationExpression(node, targetEntity);
3971 private bool ProcessMetaMethodInvocation(MethodInvocationExpression node)
3973 IEntity targetEntity = node.Target.Entity;
3974 if (null == targetEntity) return false;
3975 if (!IsOrContainMetaMethod(targetEntity)) return false;
3977 object[] arguments = GetMetaMethodInvocationArguments(node);
3978 Type[] argumentTypes = MethodResolver.GetArgumentTypes(arguments);
3979 MethodResolver resolver = new MethodResolver(argumentTypes);
3980 CandidateMethod method = resolver.ResolveMethod(EnumerateMetaMethods(targetEntity));
3981 if (null == method) return false;
3983 // TODO: cache emitted dispatchers
3984 MethodDispatcherEmitter emitter = new MethodDispatcherEmitter(method, argumentTypes);
3985 Node replacement = (Node)emitter.Emit()(null, arguments);
3986 ReplaceMetaMethodInvocationSite(node, replacement);
3988 return true;
3991 private static object[] GetMetaMethodInvocationArguments(MethodInvocationExpression node)
3993 if (node.NamedArguments.Count == 0) return node.Arguments.ToArray();
3995 List arguments = new List();
3996 arguments.Add(node.NamedArguments.ToArray());
3997 arguments.Extend(node.Arguments);
3998 return arguments.ToArray();
4001 private void ReplaceMetaMethodInvocationSite(MethodInvocationExpression node, Node replacement)
4003 if (replacement is Statement)
4005 if (node.ParentNode.NodeType != NodeType.ExpressionStatement)
4006 NotImplemented(node, "Cant use an statement where an expression is expected.");
4007 node.ParentNode.ParentNode.Replace(node.ParentNode, replacement);
4009 else
4011 node.ParentNode.Replace(node, replacement);
4013 Visit(replacement);
4016 private System.Collections.Generic.IEnumerable<System.Reflection.MethodInfo> EnumerateMetaMethods(IEntity entity)
4018 if (entity.EntityType == EntityType.Method)
4020 yield return GetMethodInfo(entity);
4022 else
4024 foreach (IEntity item in ((Ambiguous)entity).Entities)
4026 yield return GetMethodInfo(item);
4031 private static MethodInfo GetMethodInfo(IEntity entity)
4033 return (MethodInfo)((ExternalMethod) entity).MethodInfo;
4036 private bool IsOrContainMetaMethod(IEntity entity)
4038 switch (entity.EntityType)
4040 case EntityType.Ambiguous:
4041 return ((Ambiguous) entity).Any(IsMetaMethod);
4042 case EntityType.Method:
4043 return IsMetaMethod(entity);
4045 return false;
4048 private static bool IsMetaMethod(IEntity entity)
4050 ExternalMethod m = entity as ExternalMethod;
4051 if (m == null) return false;
4052 return m.IsMeta;
4055 private void ProcessMethodInvocationExpression(MethodInvocationExpression node, IEntity targetEntity)
4057 switch (targetEntity.EntityType)
4059 case EntityType.Ambiguous:
4061 ProcessAmbiguousMethodInvocation(node, targetEntity);
4062 break;
4064 case EntityType.BuiltinFunction:
4066 ProcessBuiltinInvocation((BuiltinFunction)targetEntity, node);
4067 break;
4069 case EntityType.Event:
4071 ProcessEventInvocation((IEvent)targetEntity, node);
4072 break;
4075 case EntityType.Method:
4077 ProcessMethodInvocation(node, targetEntity);
4078 break;
4081 case EntityType.Constructor:
4083 ProcessConstructorInvocation(node, targetEntity);
4084 break;
4087 case EntityType.Type:
4089 ProcessTypeInvocation(node);
4090 break;
4093 case EntityType.Error:
4095 Error(node);
4096 break;
4099 default:
4101 ProcessGenericMethodInvocation(node);
4102 break;
4107 protected virtual void ProcessAmbiguousMethodInvocation(MethodInvocationExpression node, IEntity targetEntity)
4109 targetEntity = ResolveAmbiguousMethodInvocation(node, (Ambiguous)targetEntity);
4110 if (null == targetEntity) return;
4111 ProcessMethodInvocationExpression(node, targetEntity);
4114 private void ProcessConstructorInvocation(MethodInvocationExpression node, IEntity targetEntity)
4116 NamedArgumentsNotAllowed(node);
4117 InternalConstructor constructorInfo = targetEntity as InternalConstructor;
4118 if (null == constructorInfo) return;
4120 IType targetType = null;
4121 if (NodeType.SuperLiteralExpression == node.Target.NodeType)
4123 constructorInfo.HasSuperCall = true;
4124 targetType = constructorInfo.DeclaringType.BaseType;
4126 else if (node.Target.NodeType == NodeType.SelfLiteralExpression)
4128 constructorInfo.HasSelfCall = true;
4129 targetType = constructorInfo.DeclaringType;
4132 IConstructor targetConstructorInfo = GetCorrectConstructor(node, targetType, node.Arguments);
4133 if (null != targetConstructorInfo)
4135 Bind(node.Target, targetConstructorInfo);
4139 protected virtual bool ProcessMethodInvocationWithInvalidParameters(MethodInvocationExpression node, IMethod targetMethod)
4141 return false;
4144 protected virtual void ProcessMethodInvocation(MethodInvocationExpression node, IEntity targetEntity)
4146 IMethod targetMethod = (IMethod)targetEntity;
4147 if (!CheckParameters(targetMethod.CallableType, node.Arguments, false)
4148 || !IsAccessible(targetMethod))
4150 if (TryToProcessAsExtensionInvocation(node)) return;
4152 if (ProcessMethodInvocationWithInvalidParameters(node, targetMethod)) return;
4154 AssertParameters(node, targetMethod, node.Arguments);
4157 AssertTargetContext(node.Target, targetMethod);
4158 NamedArgumentsNotAllowed(node);
4160 EnsureRelatedNodeWasVisited(node.Target, targetMethod);
4161 BindExpressionType(node, GetInferredType(targetMethod));
4162 ApplyBuiltinMethodTypeInference(node, targetMethod);
4165 private bool IsAccessible(IAccessibleMember method)
4167 return GetAccessibilityChecker().IsAccessible(method);
4170 private IAccessibilityChecker GetAccessibilityChecker()
4172 if (null == _currentMethod) return AccessibilityChecker.Global;
4173 return new AccessibilityChecker(CurrentTypeDefinition);
4176 private TypeDefinition CurrentTypeDefinition
4178 get { return _currentMethod.Method.DeclaringType; }
4181 private void NamedArgumentsNotAllowed(MethodInvocationExpression node)
4183 if (node.NamedArguments.Count == 0) return;
4184 Error(CompilerErrorFactory.NamedArgumentsNotAllowed(node.NamedArguments[0]));
4187 private void ProcessExtensionMethodInvocation(MethodInvocationExpression node, IEntity targetEntity)
4189 PreNormalizeExtensionInvocation(node);
4190 if (EntityType.Ambiguous == targetEntity.EntityType)
4192 targetEntity = ResolveAmbiguousExtension(node, (Ambiguous)targetEntity);
4193 if (null == targetEntity) return;
4195 IMethod targetMethod = (IMethod)targetEntity;
4196 PostNormalizationExtensionInvocation(node, targetMethod);
4197 NamedArgumentsNotAllowed(node);
4198 AssertParameters(node, targetMethod, node.Arguments);
4199 BindExpressionType(node, targetMethod.ReturnType);
4202 private IEntity ResolveAmbiguousExtension(MethodInvocationExpression node, Ambiguous ambiguous)
4204 IEntity resolved = ResolveCallableReference(node, ambiguous);
4205 if (null != resolved) return resolved;
4207 return CantResolveAmbiguousMethodInvocation(node, ambiguous.Entities);
4210 private bool IsExtensionMethod(IEntity entity)
4212 if (EntityType.Method != entity.EntityType) return false;
4213 return ((IMethod)entity).IsExtension;
4216 private bool IsOrContainsBooExtensionMethod(IEntity entity)
4218 if (entity.EntityType == EntityType.Ambiguous) return IsBooExtensionMethod(((Ambiguous)entity).Entities[0]);
4219 return IsBooExtensionMethod(entity);
4222 private bool IsBooExtensionMethod(IEntity entity)
4224 if (EntityType.Method != entity.EntityType) return false;
4225 return ((IMethod)entity).IsBooExtension;
4228 private void PostNormalizationExtensionInvocation(MethodInvocationExpression node, IMethod targetMethod)
4230 node.Target = CodeBuilder.CreateMethodReference(node.Target.LexicalInfo, targetMethod);
4233 private void PreNormalizeExtensionInvocation(MethodInvocationExpression node)
4235 node.Arguments.Insert(0, EnsureMemberReferenceForExtension(node).Target);
4238 private MemberReferenceExpression EnsureMemberReferenceForExtension(MethodInvocationExpression node)
4240 MemberReferenceExpression memberRef = node.Target as MemberReferenceExpression;
4241 if (null != memberRef) return memberRef;
4243 node.Target = memberRef = CodeBuilder.MemberReferenceForEntity(
4244 CreateSelfReference(),
4245 GetEntity(node.Target));
4247 return memberRef;
4250 private SelfLiteralExpression CreateSelfReference()
4252 return CodeBuilder.CreateSelfReference(CurrentType);
4255 protected virtual bool IsDuckTyped(IMember entity)
4257 return entity.IsDuckTyped;
4260 private IType GetInferredType(IMethod entity)
4262 return IsDuckTyped(entity)
4263 ? this.TypeSystemServices.DuckType
4264 : entity.ReturnType;
4267 private IType GetInferredType(IMember entity)
4269 Debug.Assert(EntityType.Method != entity.EntityType);
4270 return IsDuckTyped(entity)
4271 ? this.TypeSystemServices.DuckType
4272 : entity.Type;
4275 void ReplaceTypeInvocationByEval(IType type, MethodInvocationExpression node)
4277 Node parent = node.ParentNode;
4279 parent.Replace(node, EvalForTypeInvocation(type, node));
4282 private MethodInvocationExpression EvalForTypeInvocation(IType type, MethodInvocationExpression node)
4284 MethodInvocationExpression eval = CodeBuilder.CreateEvalInvocation(node.LexicalInfo);
4285 ReferenceExpression local = CreateTempLocal(node.Target.LexicalInfo, type);
4287 eval.Arguments.Add(CodeBuilder.CreateAssignment(local.CloneNode(), node));
4289 AddResolvedNamedArgumentsToEval(eval, node.NamedArguments, local);
4291 node.NamedArguments.Clear();
4293 eval.Arguments.Add(local);
4295 BindExpressionType(eval, type);
4296 return eval;
4299 private void AddResolvedNamedArgumentsToEval(MethodInvocationExpression eval, ExpressionPairCollection namedArguments, ReferenceExpression instance)
4301 foreach (ExpressionPair pair in namedArguments)
4303 if (TypeSystemServices.IsError(pair.First)) continue;
4305 AddResolvedNamedArgumentToEval(eval, pair, instance);
4309 protected virtual void AddResolvedNamedArgumentToEval(MethodInvocationExpression eval, ExpressionPair pair, ReferenceExpression instance)
4311 IEntity entity = GetEntity(pair.First);
4312 switch (entity.EntityType)
4314 case EntityType.Event:
4316 IEvent member = (IEvent)entity;
4317 eval.Arguments.Add(
4318 CodeBuilder.CreateMethodInvocation(
4319 pair.First.LexicalInfo,
4320 instance.CloneNode(),
4321 member.GetAddMethod(),
4322 pair.Second));
4323 break;
4326 case EntityType.Field:
4328 eval.Arguments.Add(
4329 CodeBuilder.CreateAssignment(
4330 pair.First.LexicalInfo,
4331 CodeBuilder.CreateMemberReference(
4332 instance.CloneNode(),
4333 (IMember)entity),
4334 pair.Second));
4335 break;
4338 case EntityType.Property:
4340 IProperty property = (IProperty)entity;
4341 IMethod setter = property.GetSetMethod();
4342 if (null == setter)
4344 Error(CompilerErrorFactory.PropertyIsReadOnly(
4345 pair.First,
4346 property.FullName));
4348 else
4350 //EnsureRelatedNodeWasVisited(pair.First, setter);
4351 eval.Arguments.Add(
4352 CodeBuilder.CreateAssignment(
4353 pair.First.LexicalInfo,
4354 CodeBuilder.CreateMemberReference(
4355 instance.CloneNode(),
4356 property),
4357 pair.Second));
4359 break;
4364 void ProcessEventInvocation(IEvent ev, MethodInvocationExpression node)
4366 NamedArgumentsNotAllowed(node);
4367 if (!EnsureInternalEventInvocation(ev, node)) return;
4369 IMethod method = ev.GetRaiseMethod();
4370 if (AssertParameters(node, method, node.Arguments))
4372 node.Target = CodeBuilder.CreateMemberReference(
4373 ((MemberReferenceExpression)node.Target).Target,
4374 method);
4375 BindExpressionType(node, method.ReturnType);
4379 public bool EnsureInternalEventInvocation(IEvent ev, MethodInvocationExpression node)
4381 if (ev.IsAbstract || ev.IsVirtual || ev.DeclaringType == CurrentType)
4382 return true;
4384 Error(CompilerErrorFactory.EventCanOnlyBeInvokedFromWithinDeclaringClass(node, ev));
4385 return false;
4388 void ProcessCallableTypeInvocation(MethodInvocationExpression node, ICallableType type)
4390 NamedArgumentsNotAllowed(node);
4392 if (node.Arguments.Count == 1)
4394 AssertTypeCompatibility(node.Arguments[0], type, GetExpressionType(node.Arguments[0]));
4395 node.ParentNode.Replace(
4396 node,
4397 CodeBuilder.CreateCast(
4398 type,
4399 node.Arguments[0]));
4401 else
4403 IConstructor ctor = GetCorrectConstructor(node, type, node.Arguments);
4404 if (null != ctor)
4406 BindConstructorInvocation(node, ctor);
4408 else
4410 Error(node);
4415 void ProcessTypeInvocation(MethodInvocationExpression node)
4417 IType type = (IType)node.Target.Entity;
4419 ICallableType callableType = type as ICallableType;
4420 if (null != callableType)
4422 ProcessCallableTypeInvocation(node, callableType);
4423 return;
4426 if (!AssertCanCreateInstance(node.Target, type))
4428 Error(node);
4429 return;
4432 ResolveNamedArguments(type, node.NamedArguments);
4433 if (type.IsValueType && node.Arguments.Count == 0)
4435 ProcessValueTypeInstantiation(type, node);
4436 return;
4439 IConstructor ctor = GetCorrectConstructor(node, type, node.Arguments);
4440 if (null != ctor)
4442 BindConstructorInvocation(node, ctor);
4444 if (node.NamedArguments.Count > 0)
4446 ReplaceTypeInvocationByEval(type, node);
4449 else
4451 Error(node);
4455 void BindConstructorInvocation(MethodInvocationExpression node, IConstructor ctor)
4457 // rebind the target now we know
4458 // it is a constructor call
4459 Bind(node.Target, ctor);
4460 BindExpressionType(node.Target, ctor.Type);
4461 BindExpressionType(node, ctor.DeclaringType);
4464 private void ProcessValueTypeInstantiation(IType type, MethodInvocationExpression node)
4466 // XXX: naive and unoptimized but correct approach
4467 // simply initialize a new temporary value type
4468 // TODO: OPTIMIZE by detecting assignments to local variables
4470 MethodInvocationExpression eval = CodeBuilder.CreateEvalInvocation(node.LexicalInfo);
4471 BindExpressionType(eval, type);
4473 InternalLocal local = DeclareTempLocal(type);
4474 ReferenceExpression localReference = CodeBuilder.CreateReference(local);
4475 eval.Arguments.Add(CodeBuilder.CreateDefaultInitializer(node.LexicalInfo, local));
4476 AddResolvedNamedArgumentsToEval(eval, node.NamedArguments, localReference);
4477 eval.Arguments.Add(localReference);
4479 node.ParentNode.Replace(node, eval);
4482 void ProcessGenericMethodInvocation(MethodInvocationExpression node)
4484 IType type = GetExpressionType(node.Target);
4485 if (TypeSystemServices.IsCallable(type))
4487 ProcessMethodInvocationOnCallableExpression(node);
4489 else
4491 Error(node,
4492 CompilerErrorFactory.TypeIsNotCallable(node.Target, type.ToString()));
4496 void ProcessMethodInvocationOnCallableExpression(MethodInvocationExpression node)
4498 IType type = node.Target.ExpressionType;
4500 ICallableType delegateType = type as ICallableType;
4501 if (null != delegateType)
4503 if (AssertParameters(node.Target, delegateType, delegateType, node.Arguments))
4505 IMethod invoke = ResolveMethod(delegateType, "Invoke");
4506 node.Target = CodeBuilder.CreateMemberReference(node.Target, invoke);
4507 BindExpressionType(node, invoke.ReturnType);
4509 else
4511 Error(node);
4514 else if (TypeSystemServices.ICallableType.IsAssignableFrom(type))
4516 node.Target = CodeBuilder.CreateMemberReference(node.Target, ICallable_Call);
4517 ArrayLiteralExpression arg = CodeBuilder.CreateObjectArray(node.Arguments);
4518 node.Arguments.Clear();
4519 node.Arguments.Add(arg);
4521 BindExpressionType(node, ICallable_Call.ReturnType);
4523 else if (TypeSystemServices.TypeType == type)
4525 ProcessSystemTypeInvocation(node);
4527 else
4529 ProcessInvocationOnUnknownCallableExpression(node);
4533 private void ProcessSystemTypeInvocation(MethodInvocationExpression node)
4535 MethodInvocationExpression invocation = CreateInstanceInvocationFor(node);
4536 if (invocation.NamedArguments.Count == 0)
4538 node.ParentNode.Replace(node, invocation);
4539 return;
4541 ProcessNamedArgumentsForTypeInvocation(invocation);
4542 node.ParentNode.Replace(node, EvalForTypeInvocation(TypeSystemServices.ObjectType, invocation));
4545 private void ProcessNamedArgumentsForTypeInvocation(MethodInvocationExpression invocation)
4547 foreach (ExpressionPair pair in invocation.NamedArguments)
4549 if (!ProcessNamedArgument(pair)) continue;
4550 NamedArgumentNotFound(TypeSystemServices.ObjectType, (ReferenceExpression)pair.First);
4554 private MethodInvocationExpression CreateInstanceInvocationFor(MethodInvocationExpression node)
4556 MethodInvocationExpression invocation = CodeBuilder.CreateMethodInvocation(Activator_CreateInstance, node.Target);
4557 if (Activator_CreateInstance.AcceptVarArgs)
4559 invocation.Arguments.Extend(node.Arguments);
4561 else
4563 invocation.Arguments.Add(CodeBuilder.CreateObjectArray(node.Arguments));
4565 invocation.NamedArguments = node.NamedArguments;
4566 return invocation;
4569 protected virtual void ProcessInvocationOnUnknownCallableExpression(MethodInvocationExpression node)
4571 NotImplemented(node, "Method invocation on type '" + node.Target.ExpressionType + "'.");
4574 bool AssertIdentifierName(Node node, string name)
4576 if (TypeSystemServices.IsPrimitive(name))
4578 Error(CompilerErrorFactory.CantRedefinePrimitive(node, name));
4579 return false;
4581 return true;
4584 private bool CheckIsNotValueType(BinaryExpression node, Expression expression)
4586 IType tag = GetExpressionType(expression);
4587 if (tag.IsValueType)
4589 Error(CompilerErrorFactory.OperatorCantBeUsedWithValueType(
4590 expression,
4591 GetBinaryOperatorText(node.Operator),
4592 tag.ToString()));
4594 return false;
4596 return true;
4599 void BindAssignmentToSlice(BinaryExpression node)
4601 SlicingExpression slice = (SlicingExpression)node.Left;
4603 if (!IsAmbiguous(slice.Target.Entity)
4604 && GetExpressionType(slice.Target).IsArray)
4606 BindAssignmentToSliceArray(node);
4608 else if (TypeSystemServices.IsDuckTyped(slice.Target))
4610 BindExpressionType(node, TypeSystemServices.DuckType);
4612 else
4614 BindAssignmentToSliceProperty(node);
4618 void BindAssignmentToSliceArray(BinaryExpression node)
4620 SlicingExpression slice = (SlicingExpression)node.Left;
4622 IArrayType sliceTargetType = (IArrayType)GetExpressionType(slice.Target);
4623 IType lhsType = GetExpressionType(node.Right);
4625 foreach (Slice item in slice.Indices)
4627 if (!AssertTypeCompatibility(item.Begin, TypeSystemServices.IntType, GetExpressionType(item.Begin)))
4629 Error(node);
4630 return;
4634 if (slice.Indices.Count > 1)
4636 if (AstUtil.IsComplexSlicing(slice))
4638 // FIXME: Check type compatibility
4639 BindAssignmentToComplexSliceArray(node);
4641 else
4643 if (!AssertTypeCompatibility(node.Right, sliceTargetType.GetElementType(), lhsType))
4645 Error(node);
4646 return;
4648 BindAssignmentToSimpleSliceArray(node);
4651 else
4653 if (!AssertTypeCompatibility(node.Right, sliceTargetType.GetElementType(), lhsType))
4655 Error(node);
4656 return;
4658 node.ExpressionType = sliceTargetType.GetElementType();
4662 void BindAssignmentToSimpleSliceArray(BinaryExpression node)
4664 SlicingExpression slice = (SlicingExpression)node.Left;
4665 MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation(
4666 slice.Target,
4667 TypeSystemServices.Map(typeof(Array).GetMethod("SetValue", new Type[] { typeof(object), typeof(int[]) })),
4668 node.Right);
4669 for (int i = 0; i < slice.Indices.Count; i++)
4671 mie.Arguments.Add(slice.Indices[i].Begin);
4673 BindExpressionType(mie, TypeSystemServices.VoidType);
4674 node.ParentNode.Replace(node, mie);
4677 void BindAssignmentToComplexSliceArray(BinaryExpression node)
4679 SlicingExpression slice = (SlicingExpression)node.Left;
4680 ArrayLiteralExpression ale = new ArrayLiteralExpression();
4681 ArrayLiteralExpression collapse = new ArrayLiteralExpression();
4682 for (int i = 0; i < slice.Indices.Count; i++)
4684 ale.Items.Add(slice.Indices[i].Begin);
4685 if (null == slice.Indices[i].End ||
4686 OmittedExpression.Default == slice.Indices[i].End)
4688 ale.Items.Add(new IntegerLiteralExpression(1 + (int)((IntegerLiteralExpression)slice.Indices[i].Begin).Value));
4689 collapse.Items.Add(new BoolLiteralExpression(true));
4691 else
4693 ale.Items.Add(slice.Indices[i].End);
4694 collapse.Items.Add(new BoolLiteralExpression(false));
4698 MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation(
4699 RuntimeServices_SetMultiDimensionalRange1,
4700 node.Right,
4701 slice.Target,
4702 ale);
4704 mie.Arguments.Add(collapse);
4706 BindExpressionType(mie, TypeSystemServices.VoidType);
4707 BindExpressionType(ale, TypeSystemServices.Map(typeof(int[])));
4708 BindExpressionType(collapse, TypeSystemServices.Map(typeof(bool[])));
4709 node.ParentNode.Replace(node, mie);
4712 void BindAssignmentToSliceProperty(BinaryExpression node)
4714 SlicingExpression slice = (SlicingExpression)node.Left;
4716 IEntity lhs = GetEntity(node.Left);
4717 IMethod setter = null;
4719 MethodInvocationExpression mie = new MethodInvocationExpression(node.Left.LexicalInfo);
4720 foreach (Slice index in slice.Indices)
4722 mie.Arguments.Add(index.Begin);
4724 mie.Arguments.Add(node.Right);
4726 if (EntityType.Property == lhs.EntityType)
4728 IMethod setMethod = ((IProperty)lhs).GetSetMethod();
4729 if (null == setMethod)
4731 Error(node, CompilerErrorFactory.PropertyIsReadOnly(slice.Target, lhs.FullName));
4732 return;
4734 if (AssertParameters(node.Left, setMethod, mie.Arguments))
4736 setter = setMethod;
4739 else if (EntityType.Ambiguous == lhs.EntityType)
4741 setter = (IMethod)GetCorrectCallableReference(node.Left, mie.Arguments, GetSetMethods(lhs));
4742 if (setter == null)
4744 Error(node.Left);
4745 return;
4749 if (null == setter)
4751 Error(node, CompilerErrorFactory.LValueExpected(node.Left));
4753 else
4755 mie.Target = CodeBuilder.CreateMemberReference(
4756 GetIndexedPropertySlicingTarget(slice),
4757 setter);
4758 BindExpressionType(mie, setter.ReturnType);
4759 node.ParentNode.Replace(node, mie);
4763 private IEntity[] GetSetMethods(IEntity candidates)
4765 return GetSetMethods(((Ambiguous)candidates).Entities);
4768 void BindAssignment(BinaryExpression node)
4770 BindNullableOperation(node);
4772 if (NodeType.SlicingExpression == node.Left.NodeType)
4774 BindAssignmentToSlice(node);
4776 else
4778 ProcessAssignment(node);
4782 virtual protected void ProcessAssignment(BinaryExpression node)
4784 TryToResolveAmbiguousAssignment(node);
4785 ValidateAssignment(node);
4786 BindExpressionType(node, GetExpressionType(node.Right));
4789 virtual protected void ValidateAssignment(BinaryExpression node)
4791 IEntity lhs = node.Left.Entity;
4792 IType rtype = GetExpressionType(node.Right);
4793 if (AssertLValue(node.Left, lhs))
4795 IType lhsType = GetExpressionType(node.Left);
4796 AssertTypeCompatibility(node.Right, lhsType, rtype);
4797 CheckAssignmentToIndexedProperty(node.Left, lhs);
4801 virtual protected void TryToResolveAmbiguousAssignment(BinaryExpression node)
4803 IEntity lhs = node.Left.Entity;
4804 if (null == lhs) return;
4805 if (EntityType.Ambiguous != lhs.EntityType) return;
4807 Expression lvalue = node.Left;
4808 lhs = ResolveAmbiguousLValue(lvalue, (Ambiguous)lhs, node.Right);
4809 if (NodeType.ReferenceExpression == lvalue.NodeType)
4811 IMember member = lhs as IMember;
4812 if (null != member)
4814 ResolveMemberInfo((ReferenceExpression)lvalue, member);
4819 private void CheckAssignmentToIndexedProperty(Node node, IEntity lhs)
4821 IProperty property = lhs as IProperty;
4822 if (null != property && IsIndexedProperty(property))
4824 Error(CompilerErrorFactory.PropertyRequiresParameters(AstUtil.GetMemberAnchor(node), property.FullName));
4828 bool CheckIsaArgument(Expression e)
4830 if (TypeSystemServices.TypeType != GetExpressionType(e))
4832 Error(CompilerErrorFactory.IsaArgument(e));
4833 return false;
4835 return true;
4838 bool BindNullableOperation(BinaryExpression node)
4840 if (!IsNullableOperation(node))
4842 return false;
4845 if (BinaryOperatorType.ReferenceEquality == node.Operator)
4847 node.Operator = BinaryOperatorType.Equality;
4849 else if (BinaryOperatorType.ReferenceInequality == node.Operator)
4851 node.Operator = BinaryOperatorType.Inequality;
4854 IType lhs, rhs;
4855 if (BinaryOperatorType.Assign == node.Operator)
4857 lhs = GetExpressionType(node.Left);
4858 rhs = GetExpressionType(node.Right);
4859 bool lhsIsNullable = TypeSystemServices.IsNullable(lhs);
4860 if (lhsIsNullable && TypeSystemServices.IsNullable(rhs))
4862 return false;
4864 if (lhsIsNullable)
4866 BindNullableInitializer(node, node.Right, lhs);
4867 return false;
4870 else if (IsNull(node.Left) || IsNull(node.Right))
4872 Expression nullable = IsNull(node.Left) ? node.Right : node.Left;
4873 Expression val = new MemberReferenceExpression(nullable, "HasValue");
4874 node.Replace(node.Left, val);
4875 Visit(val);
4876 Expression nil = new BoolLiteralExpression(false);
4877 node.Replace(node.Right, nil);
4878 Visit(nil);
4879 BindExpressionType(node, TypeSystemServices.BoolType);
4880 return true;
4883 if (BinaryOperatorType.Equality != node.Operator
4884 && BinaryOperatorType.Inequality != node.Operator)
4886 lhs = GetExpressionType(node.Left);
4887 if (TypeSystemServices.IsNullable(lhs))
4889 Expression val = new MemberReferenceExpression(node.Left, "Value");
4890 node.Replace(node.Left, val);
4891 Visit(val);
4893 rhs = GetExpressionType(node.Right);
4894 if (TypeSystemServices.IsNullable(rhs))
4896 Expression val = new MemberReferenceExpression(node.Right, "Value");
4897 node.Replace(node.Right, val);
4898 Visit(val);
4902 return false;
4905 void BindNullableInitializer(Node node, Expression val, IType type)
4907 MethodInvocationExpression mie = new MethodInvocationExpression();
4908 GenericReferenceExpression gre = new GenericReferenceExpression();
4909 gre.Target = new MemberReferenceExpression(new ReferenceExpression("System"), "Nullable");
4910 gre.GenericArguments.Add(TypeReference.Lift(Nullable.GetUnderlyingType(((ExternalType) type).ActualType)));
4911 mie.Target = gre;
4912 if (!IsNull(val))
4914 mie.Arguments.Add(val);
4916 node.Replace(val, mie);
4917 Visit(mie);
4920 void BindTypeTest(BinaryExpression node)
4922 if (CheckIsNotValueType(node, node.Left) &&
4923 CheckIsaArgument(node.Right))
4925 BindExpressionType(node, TypeSystemServices.BoolType);
4927 else
4929 Error(node);
4933 void BindReferenceEquality(BinaryExpression node)
4935 if (BindNullableOperation(node))
4937 return;
4940 if (CheckIsNotValueType(node, node.Left) &&
4941 CheckIsNotValueType(node, node.Right))
4943 BindExpressionType(node, TypeSystemServices.BoolType);
4945 else
4947 Error(node);
4951 void BindInPlaceArithmeticOperator(BinaryExpression node)
4953 if (IsArraySlicing(node.Left))
4955 BindInPlaceArithmeticOperatorOnArraySlicing(node);
4956 return;
4959 Node parent = node.ParentNode;
4961 Expression target = node.Left;
4962 if (null != target.Entity && EntityType.Property == target.Entity.EntityType)
4964 // if target is a property force a rebinding
4965 target.ExpressionType = null;
4968 BinaryExpression assign = ExpandInPlaceBinaryExpression(node);
4969 parent.Replace(node, assign);
4970 Visit(assign);
4973 protected BinaryExpression ExpandInPlaceBinaryExpression(BinaryExpression node)
4975 BinaryExpression assign = new BinaryExpression(node.LexicalInfo);
4976 assign.Operator = BinaryOperatorType.Assign;
4977 assign.Left = node.Left.CloneNode();
4978 assign.Right = node;
4979 node.Operator = GetRelatedBinaryOperatorForInPlaceOperator(node.Operator);
4980 return assign;
4983 private void BindInPlaceArithmeticOperatorOnArraySlicing(BinaryExpression node)
4985 Node parent = node.ParentNode;
4986 Expression expansion = CreateSideEffectAwareSlicingOperation(
4987 node.LexicalInfo,
4988 GetRelatedBinaryOperatorForInPlaceOperator(node.Operator),
4989 (SlicingExpression) node.Left,
4990 node.Right,
4991 null);
4992 parent.Replace(node, expansion);
4995 BinaryOperatorType GetRelatedBinaryOperatorForInPlaceOperator(BinaryOperatorType op)
4997 switch (op)
4999 case BinaryOperatorType.InPlaceAddition:
5000 return BinaryOperatorType.Addition;
5002 case BinaryOperatorType.InPlaceSubtraction:
5003 return BinaryOperatorType.Subtraction;
5005 case BinaryOperatorType.InPlaceMultiply:
5006 return BinaryOperatorType.Multiply;
5008 case BinaryOperatorType.InPlaceDivision:
5009 return BinaryOperatorType.Division;
5011 case BinaryOperatorType.InPlaceBitwiseAnd:
5012 return BinaryOperatorType.BitwiseAnd;
5014 case BinaryOperatorType.InPlaceBitwiseOr:
5015 return BinaryOperatorType.BitwiseOr;
5017 case BinaryOperatorType.InPlaceShiftLeft:
5018 return BinaryOperatorType.ShiftLeft;
5020 case BinaryOperatorType.InPlaceShiftRight:
5021 return BinaryOperatorType.ShiftRight;
5023 throw new ArgumentException("op");
5026 void BindArrayAddition(BinaryExpression node)
5028 IArrayType lhs = (IArrayType)GetExpressionType(node.Left);
5029 IArrayType rhs = (IArrayType)GetExpressionType(node.Right);
5031 if (lhs.GetElementType() == rhs.GetElementType())
5033 node.ParentNode.Replace(
5034 node,
5035 CodeBuilder.CreateCast(
5036 lhs,
5037 CodeBuilder.CreateMethodInvocation(
5038 RuntimeServices_AddArrays,
5039 CodeBuilder.CreateTypeofExpression(lhs.GetElementType()),
5040 node.Left,
5041 node.Right)));
5043 else
5045 InvalidOperatorForTypes(node);
5049 void BindArithmeticOperator(BinaryExpression node)
5051 BindNullableOperation(node);
5053 IType left = GetExpressionType(node.Left);
5054 IType right = GetExpressionType(node.Right);
5055 if (IsPrimitiveNumber(left) && IsPrimitiveNumber(right))
5057 BindExpressionType(node, TypeSystemServices.GetPromotedNumberType(left, right));
5059 else if (!ResolveOperator(node))
5061 InvalidOperatorForTypes(node);
5065 static string GetBinaryOperatorText(BinaryOperatorType op)
5067 return BooPrinterVisitor.GetBinaryOperatorText(op);
5070 static string GetUnaryOperatorText(UnaryOperatorType op)
5072 return BooPrinterVisitor.GetUnaryOperatorText(op);
5075 IEntity ResolveName(Node node, string name)
5077 IEntity tag = NameResolutionService.Resolve(name);
5078 CheckNameResolution(node, name, tag);
5080 return tag;
5083 bool CheckNameResolution(Node node, string name, IEntity tag)
5085 if (null == tag)
5087 Error(CompilerErrorFactory.UnknownIdentifier(node, name));
5088 return false;
5090 return true;
5093 private bool IsPublicEvent(IEntity tag)
5095 return (EntityType.Event == tag.EntityType) && ((IMember)tag).IsPublic;
5098 private bool IsPublicFieldPropertyEvent(IEntity entity)
5100 return IsFieldPropertyOrEvent(entity) && ((IMember)entity).IsPublic;
5103 private static bool IsFieldPropertyOrEvent(IEntity entity)
5105 return ((EntityType.Field|EntityType.Property|EntityType.Event) & entity.EntityType) > 0;
5108 private IMember ResolvePublicFieldPropertyEvent(Expression sourceNode, IType type, string name)
5110 IEntity candidate = ResolveFieldPropertyEvent(type, name);
5111 if (null == candidate) return null;
5113 if (IsPublicFieldPropertyEvent(candidate)) return (IMember)candidate;
5115 if (candidate.EntityType != EntityType.Ambiguous) return null;
5117 IList found = ((Ambiguous)candidate).Select(IsPublicFieldPropertyEvent);
5118 if (found.Count == 0) return null;
5119 if (found.Count == 1) return (IMember)found[0];
5121 Error(sourceNode, CompilerErrorFactory.AmbiguousReference(sourceNode, name, found));
5122 return null;
5125 protected IEntity ResolveFieldPropertyEvent(IType type, string name)
5127 return NameResolutionService.Resolve(type, name, EntityType.Property|EntityType.Event|EntityType.Field);
5130 void ResolveNamedArguments(IType type, ExpressionPairCollection arguments)
5132 foreach (ExpressionPair arg in arguments)
5134 if (!ProcessNamedArgument(arg)) continue;
5135 ResolveNamedArgument(type, (ReferenceExpression)arg.First, arg.Second);
5139 private bool ProcessNamedArgument(ExpressionPair arg)
5141 Visit(arg.Second);
5142 if (NodeType.ReferenceExpression != arg.First.NodeType)
5144 Error(arg.First, CompilerErrorFactory.NamedParameterMustBeIdentifier(arg));
5145 return false;
5147 return true;
5150 void ResolveNamedArgument(IType type, ReferenceExpression name, Expression value)
5152 IMember member = ResolvePublicFieldPropertyEvent(name, type, name.Name);
5153 if (null == member)
5155 NamedArgumentNotFound(type, name);
5156 return;
5159 EnsureRelatedNodeWasVisited(name, member);
5160 Bind(name, member);
5162 IType memberType = member.Type;
5163 if (member.EntityType == EntityType.Event)
5165 AssertDelegateArgument(value, member, GetExpressionType(value));
5167 else
5169 AssertTypeCompatibility(value, memberType, GetExpressionType(value));
5173 protected virtual void NamedArgumentNotFound(IType type, ReferenceExpression name)
5175 Error(name, CompilerErrorFactory.NotAPublicFieldOrProperty(name, type.ToString(), name.Name));
5178 bool AssertTypeCompatibility(Node sourceNode, IType expectedType, IType actualType)
5180 if (TypeSystemServices.IsError(expectedType)
5181 || TypeSystemServices.IsError(actualType))
5183 return false;
5186 if (!TypeSystemServices.AreTypesRelated(expectedType, actualType))
5188 Error(CompilerErrorFactory.IncompatibleExpressionType(sourceNode, expectedType.ToString(), actualType.ToString()));
5189 return false;
5191 return true;
5194 bool AssertDelegateArgument(Node sourceNode, ITypedEntity delegateMember, ITypedEntity argumentInfo)
5196 if (!delegateMember.Type.IsAssignableFrom(argumentInfo.Type))
5198 Error(CompilerErrorFactory.EventArgumentMustBeAMethod(sourceNode, delegateMember.FullName, delegateMember.Type.ToString()));
5199 return false;
5201 return true;
5204 bool CheckParameterTypesStrictly(IMethod method, ExpressionCollection args)
5206 IParameter[] parameters = method.GetParameters();
5207 for (int i=0; i<args.Count; ++i)
5209 IType expressionType = GetExpressionType(args[i]);
5210 IType parameterType = parameters[i].Type;
5211 if (!IsAssignableFrom(parameterType, expressionType) &&
5212 !(IsNumber(expressionType) && IsNumber(parameterType))
5213 && TypeSystemServices.FindImplicitConversionOperator(expressionType,parameterType) == null)
5215 return false;
5218 return true;
5221 bool AssertParameterTypes(ICallableType method, ExpressionCollection args, int count, bool reportErrors)
5223 IParameter[] parameters = method.GetSignature().Parameters;
5224 for (int i=0; i<count; ++i)
5226 IParameter param = parameters[i];
5227 IType parameterType = param.Type;
5228 IType argumentType = GetExpressionType(args[i]);
5229 if (param.IsByRef)
5231 if (!(args[i] is ReferenceExpression
5232 || args[i] is SlicingExpression))
5234 if (reportErrors) Error(CompilerErrorFactory.RefArgTakesLValue(args[i]));
5235 return false;
5237 if (!_callableResolution.IsValidByRefArg(param, parameterType, argumentType, args[i]))
5239 return false;
5242 else
5244 if (!TypeSystemServices.AreTypesRelated(parameterType, argumentType))
5246 return false;
5250 return true;
5253 bool AssertParameters(Node sourceNode, IMethod method, ExpressionCollection args)
5255 return AssertParameters(sourceNode, method, method.CallableType, args);
5258 bool AcceptVarArgs(ICallableType method)
5260 return method.GetSignature().AcceptVarArgs;
5263 bool AssertParameters(Node sourceNode, IEntity sourceEntity, ICallableType method, ExpressionCollection args)
5265 if (CheckParameters(method, args, true)) return true;
5267 Error(CompilerErrorFactory.MethodSignature(sourceNode, sourceEntity.ToString(), GetSignature(args)));
5268 return false;
5271 private bool CheckParameters(ICallableType method, ExpressionCollection args, bool reportErrors)
5273 return AcceptVarArgs(method)
5274 ? CheckVarArgsParameters(method, args)
5275 : CheckExactArgsParameters(method, args, reportErrors);
5278 bool CheckVarArgsParameters(ICallableType method, ExpressionCollection args)
5280 return _callableResolution.IsValidVargsInvocation(method.GetSignature().Parameters, args);
5283 bool CheckExactArgsParameters(ICallableType method, ExpressionCollection args, bool reportErrors)
5285 if (method.GetSignature().Parameters.Length != args.Count) return false;
5286 return AssertParameterTypes(method, args, args.Count, reportErrors);
5289 bool IsRuntimeIterator(IType type)
5291 return TypeSystemServices.IsSystemObject(type)
5292 || IsTextReader(type);
5295 bool IsTextReader(IType type)
5297 return IsAssignableFrom(typeof(TextReader), type);
5300 bool AssertTargetContext(Expression targetContext, IMember member)
5302 if (member.IsStatic) return true;
5303 if (NodeType.MemberReferenceExpression != targetContext.NodeType) return true;
5305 Expression targetReference = ((MemberReferenceExpression)targetContext).Target;
5306 IEntity entity = targetReference.Entity;
5307 if ((null != entity && EntityType.Type == entity.EntityType)
5308 || (NodeType.SelfLiteralExpression == targetReference.NodeType
5309 && _currentMethod.IsStatic))
5311 Error(CompilerErrorFactory.InstanceRequired(targetContext, member.DeclaringType.ToString(), member.Name));
5312 return false;
5314 return true;
5317 static bool IsAssignableFrom(IType expectedType, IType actualType)
5319 return expectedType.IsAssignableFrom(actualType);
5322 bool IsAssignableFrom(Type expectedType, IType actualType)
5324 return TypeSystemServices.Map(expectedType).IsAssignableFrom(actualType);
5327 bool IsNumber(IType type)
5329 return TypeSystemServices.IsNumber(type);
5332 bool IsPrimitiveNumber(IType type)
5334 return TypeSystemServices.IsPrimitiveNumber(type);
5337 bool IsPrimitiveNumber(Expression expression)
5339 return IsPrimitiveNumber(GetExpressionType(expression));
5342 IConstructor GetCorrectConstructor(Node sourceNode, IType type, ExpressionCollection arguments)
5344 IConstructor[] constructors = type.GetConstructors();
5345 if (null != constructors && constructors.Length > 0)
5347 return (IConstructor)GetCorrectCallableReference(sourceNode, arguments, constructors);
5349 else
5351 if (!TypeSystemServices.IsError(type))
5353 if (null == (type as IGenericParameter))
5355 Error(CompilerErrorFactory.NoApropriateConstructorFound(sourceNode, type.ToString(), GetSignature(arguments)));
5357 else
5359 Error(CompilerErrorFactory.CannotCreateAnInstanceOfGenericParameterWithoutDefaultConstructorConstraint(sourceNode, type.ToString()));
5363 return null;
5366 IEntity GetCorrectCallableReference(Node sourceNode, ExpressionCollection args, IEntity[] candidates)
5368 // BOO-844: Ensure all candidates were visited (to make property setters have correct signature)
5369 foreach (IEntity candidate in candidates)
5371 EnsureRelatedNodeWasVisited(sourceNode, candidate);
5374 IEntity found = _callableResolution.ResolveCallableReference(args, candidates);
5375 if (null == found) EmitCallableResolutionError(sourceNode, candidates, args);
5376 return found;
5379 private void EmitCallableResolutionError(Node sourceNode, IEntity[] candidates, ExpressionCollection args)
5381 if (_callableResolution.ValidCandidates.Count > 1)
5383 Error(CompilerErrorFactory.AmbiguousReference(sourceNode, candidates[0].Name, _callableResolution.ValidCandidates));
5385 else
5387 IEntity candidate = candidates[0];
5388 IConstructor constructor = candidate as IConstructor;
5389 if (null != constructor)
5391 Error(CompilerErrorFactory.NoApropriateConstructorFound(sourceNode, constructor.DeclaringType.ToString(), GetSignature(args)));
5393 else
5395 Error(CompilerErrorFactory.NoApropriateOverloadFound(sourceNode, GetSignature(args), candidate.FullName));
5400 override protected void EnsureRelatedNodeWasVisited(Node sourceNode, IEntity entity)
5402 IInternalEntity internalInfo = entity as IInternalEntity;
5403 if (null == internalInfo)
5405 ITypedEntity typedEntity = entity as ITypedEntity;
5406 if (null == typedEntity) return;
5408 internalInfo = typedEntity.Type as IInternalEntity;
5409 if (null == internalInfo) return;
5412 Node node = internalInfo.Node;
5414 //member has been used so remove private member unused annotation
5415 TypeMember member = node as TypeMember;
5416 if (null != member
5417 && member.IsPrivate
5418 && member.ContainsAnnotation("PrivateMemberNeverUsed"))
5420 node.RemoveAnnotation("PrivateMemberNeverUsed");
5423 switch (node.NodeType)
5425 case NodeType.Property:
5426 case NodeType.Field:
5428 IMember memberEntity = (IMember)entity;
5429 if (EntityType.Property == entity.EntityType
5430 || TypeSystemServices.IsUnknown(memberEntity.Type))
5432 VisitMemberForTypeResolution(node);
5433 AssertTypeIsKnown(sourceNode, memberEntity, memberEntity.Type);
5435 break;
5438 case NodeType.Method:
5440 IMethod methodEntity = (IMethod)entity;
5441 if (TypeSystemServices.IsUnknown(methodEntity.ReturnType))
5443 // try to preprocess the method to resolve its return type
5444 Method method = (Method)node;
5445 PreProcessMethod(method);
5446 if (TypeSystemServices.IsUnknown(methodEntity.ReturnType))
5448 // still unknown?
5449 VisitMemberForTypeResolution(node);
5450 AssertTypeIsKnown(sourceNode, methodEntity, methodEntity.ReturnType);
5453 break;
5455 case NodeType.ClassDefinition:
5456 case NodeType.StructDefinition:
5457 case NodeType.InterfaceDefinition:
5459 if (WasVisited(node)) break;
5460 VisitInParentNamespace(node);
5461 //visit dependent attributes such as EnumeratorItemType
5462 //foreach (Attribute att in ((TypeDefinition)node).Attributes)
5464 //VisitMemberForTypeResolution(att);
5466 break;
5471 private void VisitInParentNamespace(Node node)
5473 INamespace saved = NameResolutionService.CurrentNamespace;
5476 NameResolutionService.EnterNamespace((INamespace)node.ParentNode.Entity);
5477 Visit(node);
5479 finally
5481 NameResolutionService.Restore(saved);
5486 private void AssertTypeIsKnown(Node sourceNode, IEntity sourceEntity, IType type)
5488 if (TypeSystemServices.IsUnknown(type))
5490 Error(
5491 CompilerErrorFactory.UnresolvedDependency(
5492 sourceNode,
5493 CurrentMember.FullName,
5494 sourceEntity.FullName));
5498 void VisitMemberForTypeResolution(Node node)
5500 if (WasVisited(node)) return;
5502 _context.TraceVerbose("Info {0} needs resolving.", node.Entity.Name);
5503 INamespace saved = NameResolutionService.CurrentNamespace;
5506 Visit(node);
5508 finally
5510 NameResolutionService.Restore(saved);
5514 bool ResolveOperator(UnaryExpression node)
5516 MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo);
5517 mie.Arguments.Add(node.Operand.CloneNode());
5519 string operatorName = AstUtil.GetMethodNameForOperator(node.Operator);
5520 IType operand = GetExpressionType(node.Operand);
5521 if (ResolveOperator(node, operand, operatorName, mie))
5523 return true;
5525 return ResolveOperator(node, TypeSystemServices.RuntimeServicesType, operatorName, mie);
5528 bool ResolveOperator(BinaryExpression node)
5530 MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo);
5531 mie.Arguments.Add(node.Left.CloneNode());
5532 mie.Arguments.Add(node.Right.CloneNode());
5534 string operatorName = AstUtil.GetMethodNameForOperator(node.Operator);
5535 IType lhs = GetExpressionType(node.Left);
5536 if (ResolveOperator(node, lhs, operatorName, mie))
5538 return true;
5541 IType rhs = GetExpressionType(node.Right);
5542 if (ResolveOperator(node, rhs, operatorName, mie))
5544 return true;
5546 return ResolveRuntimeOperator(node, operatorName, mie);
5549 protected virtual bool ResolveRuntimeOperator(BinaryExpression node, string operatorName, MethodInvocationExpression mie)
5551 return ResolveOperator(node, TypeSystemServices.RuntimeServicesType, operatorName, mie);
5554 IMethod ResolveAmbiguousOperator(IEntity[] entities, ExpressionCollection args)
5556 foreach (IEntity entity in entities)
5558 IMethod method = entity as IMethod;
5559 if (null != method)
5561 if (HasOperatorSignature(method, args))
5563 return method;
5567 return null;
5570 bool HasOperatorSignature(IMethod method, ExpressionCollection args)
5572 return method.IsStatic &&
5573 (args.Count == method.GetParameters().Length) &&
5574 CheckParameterTypesStrictly(method, args);
5577 IMethod FindOperator(IType type, string operatorName, ExpressionCollection args)
5579 IEntity entity = NameResolutionService.Resolve(type, operatorName, EntityType.Method);
5580 if (null != entity)
5582 IMethod method = ResolveOperatorEntity(entity, args);
5583 if (null != method) return method;
5586 entity = NameResolutionService.ResolveExtension(type, operatorName);
5587 if (null != entity)
5589 return ResolveOperatorEntity(entity, args);
5592 return null;
5595 private IMethod ResolveOperatorEntity(IEntity op, ExpressionCollection args)
5597 if (EntityType.Ambiguous == op.EntityType)
5599 return ResolveAmbiguousOperator(((Ambiguous)op).Entities, args);
5602 if (EntityType.Method == op.EntityType)
5604 IMethod candidate = (IMethod)op;
5605 if (HasOperatorSignature(candidate, args))
5607 return candidate;
5610 return null;
5613 bool ResolveOperator(Expression node, IType type, string operatorName, MethodInvocationExpression mie)
5615 IMethod entity = FindOperator(type, operatorName, mie.Arguments);
5616 if (null == entity) return false;
5617 EnsureRelatedNodeWasVisited(node, entity);
5619 mie.Target = new ReferenceExpression(entity.FullName);
5621 IMethod operatorMethod = entity;
5622 BindExpressionType(mie, operatorMethod.ReturnType);
5623 BindExpressionType(mie.Target, operatorMethod.Type);
5624 Bind(mie.Target, entity);
5626 node.ParentNode.Replace(node, mie);
5628 return true;
5631 Expression AssertBoolContext(Expression expression)
5633 IType type = GetExpressionType(expression);
5634 if (type == TypeSystemServices.BoolType) return expression;
5635 if (IsNumber(type)) return expression;
5636 if (type.IsEnum) return expression;
5638 IMethod method = TypeSystemServices.FindImplicitConversionOperator(type, TypeSystemServices.BoolType);
5639 if (null != method) return CodeBuilder.CreateMethodInvocation(method, expression);
5641 // reference types can be used in bool context
5642 if (!type.IsValueType) return expression;
5644 Error(CompilerErrorFactory.BoolExpressionRequired(expression, type.ToString()));
5645 return expression;
5648 ReferenceExpression CreateTempLocal(LexicalInfo li, IType type)
5650 InternalLocal local = DeclareTempLocal(type);
5651 ReferenceExpression reference = new ReferenceExpression(li, local.Name);
5652 reference.Entity = local;
5653 reference.ExpressionType = type;
5654 return reference;
5657 protected InternalLocal DeclareTempLocal(IType localType)
5659 return CodeBuilder.DeclareTempLocal(_currentMethod.Method, localType);
5662 IEntity DeclareLocal(Node sourceNode, string name, IType localType)
5664 return DeclareLocal(sourceNode, name, localType, false);
5667 virtual protected IEntity DeclareLocal(Node sourceNode, string name, IType localType, bool privateScope)
5669 Local local = new Local(name, privateScope);
5670 local.LexicalInfo = sourceNode.LexicalInfo;
5671 InternalLocal entity = new InternalLocal(local, localType);
5672 local.Entity = entity;
5673 _currentMethod.Method.Locals.Add(local);
5674 return entity;
5677 protected IType CurrentType
5681 return _currentMethod.DeclaringType;
5685 void PushMember(TypeMember member)
5687 _memberStack.Push(member);
5690 TypeMember CurrentMember
5694 return (TypeMember)_memberStack.Peek();
5698 void PopMember()
5700 _memberStack.Pop();
5703 void PushMethodInfo(InternalMethod tag)
5705 _methodStack.Push(_currentMethod);
5707 _currentMethod = tag;
5710 void PopMethodInfo()
5712 _currentMethod = (InternalMethod)_methodStack.Pop();
5715 void AssertHasSideEffect(Expression expression)
5717 if (!HasSideEffect(expression) && !TypeSystemServices.IsError(expression))
5719 Error(CompilerErrorFactory.ExpressionMustBeExecutedForItsSideEffects(expression));
5723 protected virtual bool HasSideEffect(Expression node)
5725 return
5726 node.NodeType == NodeType.MethodInvocationExpression ||
5727 AstUtil.IsAssignment(node) ||
5728 AstUtil.IsIncDec(node);
5731 bool AssertCanCreateInstance(Node sourceNode, IType type)
5733 if (type.IsInterface)
5735 Error(CompilerErrorFactory.CantCreateInstanceOfInterface(sourceNode, type.ToString()));
5736 return false;
5738 if (type.IsEnum)
5740 Error(CompilerErrorFactory.CantCreateInstanceOfEnum(sourceNode, type.ToString()));
5741 return false;
5743 if (type.IsAbstract)
5745 Error(CompilerErrorFactory.CantCreateInstanceOfAbstractType(sourceNode, type.ToString()));
5746 return false;
5748 if (!(type is GenericConstructedType)
5750 ((type.GenericInfo != null
5751 && type.GenericInfo.GenericParameters.Length > 0)
5752 || (type.ConstructedInfo != null
5753 && !type.ConstructedInfo.FullyConstructed))
5756 Error(CompilerErrorFactory.GenericTypesMustBeConstructedToBeInstantiated(sourceNode));
5757 return false;
5759 return true;
5762 bool AssertDeclarationName(Declaration d)
5764 if (AssertIdentifierName(d, d.Name))
5766 return AssertUniqueLocal(d);
5768 return false;
5771 bool AssertUniqueLocal(Declaration d)
5773 if (null == _currentMethod.ResolveLocal(d.Name) &&
5774 null == _currentMethod.ResolveParameter(d.Name))
5776 return true;
5778 Error(CompilerErrorFactory.LocalAlreadyExists(d, d.Name));
5779 return false;
5782 void GetDeclarationType(IType defaultDeclarationType, Declaration d)
5784 if (null != d.Type)
5786 Visit(d.Type);
5787 AssertTypeCompatibility(d, GetType(d.Type), defaultDeclarationType);
5789 else
5791 d.Type = CodeBuilder.CreateTypeReference(defaultDeclarationType);
5795 void DeclareLocal(Declaration d, bool privateScope)
5797 if (AssertIdentifierName(d, d.Name))
5799 d.Entity = DeclareLocal(d, d.Name, GetType(d.Type), privateScope);
5803 protected IType GetEnumeratorItemType(IType iteratorType)
5805 return TypeSystemServices.GetEnumeratorItemType(iteratorType);
5808 protected void ProcessDeclarationsForIterator(DeclarationCollection declarations, IType iteratorType)
5810 IType defaultDeclType = GetEnumeratorItemType(iteratorType);
5811 if (declarations.Count > 1)
5813 // will enumerate (unpack) each item
5814 defaultDeclType = GetEnumeratorItemType(defaultDeclType);
5817 foreach (Declaration d in declarations)
5819 ProcessDeclarationForIterator(d, defaultDeclType);
5823 protected void ProcessDeclarationForIterator(Declaration d, IType defaultDeclType)
5825 GetDeclarationType(defaultDeclType, d);
5826 DeclareLocal(d, true);
5829 protected virtual bool AssertLValue(Node node)
5831 IEntity entity = node.Entity;
5832 if (null != entity) return AssertLValue(node, entity);
5834 if (IsArraySlicing(node)) return true;
5835 Error(CompilerErrorFactory.LValueExpected(node));
5836 return false;
5839 protected virtual bool AssertLValue(Node node, IEntity entity)
5841 if (null != entity)
5843 switch (entity.EntityType)
5845 case EntityType.Parameter:
5846 case EntityType.Local:
5848 return true;
5851 case EntityType.Property:
5853 if (null == ((IProperty)entity).GetSetMethod())
5855 Error(CompilerErrorFactory.PropertyIsReadOnly(AstUtil.GetMemberAnchor(node), entity.FullName));
5856 return false;
5858 return true;
5861 case EntityType.Field:
5863 IField fld = (IField)entity;
5864 if (TypeSystemServices.IsReadOnlyField(fld)
5865 && !(EntityType.Constructor == _currentMethod.EntityType
5866 && _currentMethod.DeclaringType == fld.DeclaringType
5867 && fld.IsStatic == _currentMethod.IsStatic))
5869 Error(CompilerErrorFactory.FieldIsReadonly(AstUtil.GetMemberAnchor(node), entity.FullName));
5870 return false;
5872 return true;
5876 Error(CompilerErrorFactory.LValueExpected(node));
5877 return false;
5880 public static bool IsArraySlicing(Node node)
5882 if (node.NodeType != NodeType.SlicingExpression) return false;
5883 IType type = ((SlicingExpression)node).Target.ExpressionType;
5884 return null != type && type.IsArray;
5887 bool IsStandaloneReference(Node node)
5889 Node parent = node.ParentNode;
5890 if (parent is GenericReferenceExpression)
5892 parent = parent.ParentNode;
5895 return parent.NodeType != NodeType.MemberReferenceExpression;
5898 string GetSignature(IEnumerable args)
5900 StringBuilder sb = new StringBuilder("(");
5901 foreach (Expression arg in args)
5903 if (sb.Length > 1)
5905 sb.Append(", ");
5907 if (AstUtil.IsExplodeExpression(arg))
5909 sb.Append('*');
5911 sb.Append(GetExpressionType(arg));
5913 sb.Append(")");
5914 return sb.ToString();
5917 void InvalidOperatorForType(UnaryExpression node)
5919 Error(node, CompilerErrorFactory.InvalidOperatorForType(node,
5920 GetUnaryOperatorText(node.Operator),
5921 GetExpressionType(node.Operand).ToString()));
5924 void InvalidOperatorForTypes(BinaryExpression node)
5926 Error(node, CompilerErrorFactory.InvalidOperatorForTypes(node,
5927 GetBinaryOperatorText(node.Operator),
5928 GetExpressionType(node.Left).ToString(),
5929 GetExpressionType(node.Right).ToString()));
5932 void TraceReturnType(Method method, IMethod tag)
5934 _context.TraceInfo("{0}: return type for method {1} bound to {2}", method.LexicalInfo, method.Name, tag.ReturnType);
5937 #region Method bindings cache
5939 IMethod _RuntimeServices_Len;
5941 IMethod RuntimeServices_Len
5945 if (null == _RuntimeServices_Len)
5947 _RuntimeServices_Len = ResolveMethod(TypeSystemServices.RuntimeServicesType, "Len");
5949 return _RuntimeServices_Len;
5953 IMethod _RuntimeServices_Mid;
5955 IMethod RuntimeServices_Mid
5959 if (null == _RuntimeServices_Mid)
5961 _RuntimeServices_Mid = ResolveMethod(TypeSystemServices.RuntimeServicesType, "Mid");
5963 return _RuntimeServices_Mid;
5967 IMethod _RuntimeServices_NormalizeStringIndex;
5969 IMethod RuntimeServices_NormalizeStringIndex
5973 if (null == _RuntimeServices_NormalizeStringIndex)
5975 _RuntimeServices_NormalizeStringIndex = ResolveMethod(TypeSystemServices.RuntimeServicesType, "NormalizeStringIndex");
5977 return _RuntimeServices_NormalizeStringIndex;
5981 IMethod _RuntimeServices_AddArrays;
5983 IMethod RuntimeServices_AddArrays
5987 if (null == _RuntimeServices_AddArrays)
5989 _RuntimeServices_AddArrays = ResolveMethod(TypeSystemServices.RuntimeServicesType, "AddArrays");
5991 return _RuntimeServices_AddArrays;
5995 IMethod _RuntimeServices_GetRange1;
5997 IMethod RuntimeServices_GetRange1
6001 if (null == _RuntimeServices_GetRange1)
6003 _RuntimeServices_GetRange1 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetRange1");
6005 return _RuntimeServices_GetRange1;
6009 IMethod _RuntimeServices_GetRange2;
6011 IMethod RuntimeServices_GetRange2
6015 if (null == _RuntimeServices_GetRange2)
6017 _RuntimeServices_GetRange2 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetRange2");
6019 return _RuntimeServices_GetRange2;
6023 IMethod _RuntimeServices_GetMultiDimensionalRange1;
6025 IMethod RuntimeServices_GetMultiDimensionalRange1
6029 if (null == _RuntimeServices_GetMultiDimensionalRange1)
6031 _RuntimeServices_GetMultiDimensionalRange1 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetMultiDimensionalRange1");
6033 return _RuntimeServices_GetMultiDimensionalRange1;
6037 IMethod _RuntimeServices_SetMultiDimensionalRange1;
6039 IMethod RuntimeServices_SetMultiDimensionalRange1
6043 if (null == _RuntimeServices_SetMultiDimensionalRange1)
6045 _RuntimeServices_SetMultiDimensionalRange1 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "SetMultiDimensionalRange1");
6047 return _RuntimeServices_SetMultiDimensionalRange1;
6051 IMethod _RuntimeServices_GetEnumerable;
6053 IMethod RuntimeServices_GetEnumerable
6057 if (null == _RuntimeServices_GetEnumerable)
6059 _RuntimeServices_GetEnumerable = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetEnumerable");
6061 return _RuntimeServices_GetEnumerable;
6065 IMethod _RuntimeServices_EqualityOperator;
6067 IMethod RuntimeServices_EqualityOperator
6071 if (null == _RuntimeServices_EqualityOperator)
6073 _RuntimeServices_EqualityOperator = TypeSystemServices.Map(Types.RuntimeServices.GetMethod("EqualityOperator", new Type[] { Types.Object, Types.Object }));
6075 return _RuntimeServices_EqualityOperator;
6079 IMethod _Array_get_Length;
6081 IMethod Array_get_Length
6085 if (null == _Array_get_Length)
6087 _Array_get_Length = ResolveProperty(TypeSystemServices.ArrayType, "Length").GetGetMethod();
6089 return _Array_get_Length;
6093 IMethod _Array_GetLength;
6095 IMethod Array_GetLength
6099 if (null == _Array_GetLength)
6101 _Array_GetLength = ResolveMethod(TypeSystemServices.ArrayType, "GetLength");
6103 return _Array_GetLength;
6107 IMethod _String_get_Length;
6109 IMethod String_get_Length
6113 if (null == _String_get_Length)
6115 _String_get_Length = ResolveProperty(TypeSystemServices.StringType, "Length").GetGetMethod();
6117 return _String_get_Length;
6121 IMethod _String_Substring_Int;
6123 IMethod String_Substring_Int
6127 if (null == _String_Substring_Int)
6129 _String_Substring_Int = TypeSystemServices.Map(Types.String.GetMethod("Substring", new Type[] { Types.Int }));
6131 return _String_Substring_Int;
6135 IMethod _ICollection_get_Count;
6137 IMethod ICollection_get_Count
6141 if (null == _ICollection_get_Count)
6143 _ICollection_get_Count = ResolveProperty(TypeSystemServices.ICollectionType, "Count").GetGetMethod();
6145 return _ICollection_get_Count;
6149 IMethod _List_GetRange1;
6151 IMethod List_GetRange1
6155 if (null == _List_GetRange1)
6157 _List_GetRange1 = TypeSystemServices.Map(Types.List.GetMethod("GetRange", new Type[] { typeof(int) }));
6159 return _List_GetRange1;
6163 IMethod _List_GetRange2;
6165 IMethod List_GetRange2
6169 if (null == _List_GetRange2)
6171 _List_GetRange2 = TypeSystemServices.Map(Types.List.GetMethod("GetRange", new Type[] { typeof(int), typeof(int) }));
6173 return _List_GetRange2;
6177 IMethod _ICallable_Call;
6179 IMethod ICallable_Call
6183 if (null == _ICallable_Call)
6185 _ICallable_Call = ResolveMethod(TypeSystemServices.ICallableType, "Call");
6187 return _ICallable_Call;
6191 IMethod _Activator_CreateInstance;
6193 IMethod Activator_CreateInstance
6197 if (null == _Activator_CreateInstance)
6199 _Activator_CreateInstance = TypeSystemServices.Map(typeof(Activator).GetMethod("CreateInstance", new Type[] { Types.Type, Types.ObjectArray }));
6201 return _Activator_CreateInstance;
6205 IConstructor _Exception_StringConstructor;
6207 IConstructor Exception_StringConstructor
6211 if (null == _Exception_StringConstructor)
6213 _Exception_StringConstructor =
6214 TypeSystemServices.Map(
6215 Types.Exception.GetConstructor(new Type[] { typeof(string) }));
6217 return _Exception_StringConstructor;
6221 IMethod _TextReaderEnumerator_lines;
6223 IMethod TextReaderEnumerator_lines
6227 if (null == _TextReaderEnumerator_lines)
6229 _TextReaderEnumerator_lines = TypeSystemServices.Map(typeof(TextReaderEnumerator).GetMethod("lines"));
6231 return _TextReaderEnumerator_lines;
6235 public bool OptimizeNullComparisons
6237 get { return _optimizeNullComparisons; }
6238 set { _optimizeNullComparisons = value; }
6241 #endregion