2 // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
3 // All rights reserved.
5 // Redistribution and use in source and binary forms, with or without modification,
6 // are permitted provided that the following conditions are met:
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.
30 using System
.Collections
;
31 using System
.Diagnostics
;
33 using System
.Reflection
;
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
45 /// AST semantic evaluation.
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();
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()
120 if (null != _callableResolution
)
122 _callableResolution
.Dispose();
123 _callableResolution
= null;
126 _currentModule
= null;
127 _currentMethod
= 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;
158 _currentModule
= module
;
160 EnterNamespace((INamespace
)TypeSystemServices
.GetEntity(module
));
162 Visit(module
.Members
);
163 Visit(module
.AssemblyAttributes
);
168 override public void OnInterfaceDefinition(InterfaceDefinition node
)
170 if (WasVisited(node
)) return;
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
);
188 VisitBaseTypes(node
);
189 Visit(node
.Attributes
);
194 override public void OnClassDefinition(ClassDefinition node
)
196 if (WasVisited(node
)) return;
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
))
238 Method setter
= node
.Setter
;
239 Method getter
= node
.Getter
;
241 Visit(node
.Attributes
);
243 Visit(node
.Parameters
);
245 ResolvePropertyOverride(node
);
249 if (null != node
.Type
)
251 getter
.ReturnType
= node
.Type
.CloneNode();
253 getter
.Parameters
.ExtendWithClones(node
.Parameters
);
258 IType typeInfo
= null;
259 if (null != node
.Type
)
261 typeInfo
= GetType(node
.Type
);
267 typeInfo
= GetType(node
.Getter
.ReturnType
);
268 if (typeInfo
== TypeSystemServices
.VoidType
)
270 typeInfo
= TypeSystemServices
.ObjectType
;
271 node
.Getter
.ReturnType
= CodeBuilder
.CreateTypeReference(getter
.LexicalInfo
, typeInfo
);
276 typeInfo
= TypeSystemServices
.ObjectType
;
278 node
.Type
= CodeBuilder
.CreateTypeReference(node
.LexicalInfo
, typeInfo
);
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
;
294 override public void OnField(Field node
)
296 if (WasVisited(node
)) return;
299 InternalField entity
= (InternalField
)GetEntity(node
);
301 Visit(node
.Attributes
);
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
)
314 CompilerErrorFactory
.ValueTypeFieldsCannotHaveInitializers(
320 PreProcessFieldInitializer(node
);
329 if (null == node
.Type
)
331 node
.Type
= CreateTypeReference(node
.LexicalInfo
, TypeSystemServices
.ObjectType
);
334 CheckFieldType(node
.Type
);
337 bool IsValidLiteralInitializer(Expression e
)
341 case NodeType
.BoolLiteralExpression
:
342 case NodeType
.IntegerLiteralExpression
:
343 case NodeType
.DoubleLiteralExpression
:
344 case NodeType
.NullLiteralExpression
:
345 case NodeType
.StringLiteralExpression
:
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
));
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
;
380 private void PreProcessFieldInitializer(Field node
)
382 Expression initializer
= node
.Initializer
;
383 if (node
.IsFinal
&& node
.IsStatic
)
385 if (IsValidLiteralInitializer(initializer
))
387 ProcessLiteralField(node
);
392 Method method
= GetFieldsInitializerMethod(node
);
393 InternalMethod entity
= (InternalMethod
)method
.Entity
;
395 ReferenceExpression temp
= new ReferenceExpression("___temp_initializer");
396 BinaryExpression assignment
= new BinaryExpression(
398 BinaryOperatorType
.Assign
,
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
);
417 CodeBuilder
.CreateAssignment(
418 initializer
.LexicalInfo
,
419 CodeBuilder
.CreateReference(node
),
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
);
437 Method
GetFieldsInitializerMethod(Field node
)
439 TypeDefinition type
= node
.DeclaringType
;
440 string methodName
= node
.IsStatic
? "$static_initializer$" : "$initializer$";
441 Method method
= (Method
)type
[methodName
];
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
);
455 method
= CreateInitializerMethod(type
, methodName
, TypeMemberModifiers
.Static
);
456 AddInitializerToStaticConstructor(type
, (InternalMethod
)method
.Entity
);
461 method
= CreateInitializerMethod(type
, methodName
, TypeMemberModifiers
.None
);
462 AddInitializerToInstanceConstructors(type
, (InternalMethod
)method
.Entity
);
465 type
[methodName
] = 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
),
491 int GetIndexAfterSuperInvocation(Block body
)
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
)
512 Constructor
FindStaticConstructor(TypeDefinition type
)
514 foreach (TypeMember member
in type
.Members
)
516 if (member
.IsStatic
&& NodeType
.Constructor
== member
.NodeType
)
518 return (Constructor
)member
;
524 Constructor
GetStaticConstructor(TypeDefinition type
)
526 Constructor constructor
= FindStaticConstructor(type
);
527 if (null == constructor
)
529 constructor
= CreateStaticConstructor(type
);
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
);
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
))
568 Visit(node
.Attributes
);
569 Visit(node
.Parameters
);
571 InternalConstructor entity
= (InternalConstructor
)node
.Entity
;
572 ProcessMethodBody(entity
);
576 CheckRuntimeMethod(node
);
580 if (entity
.DeclaringType
.IsValueType
)
582 if (0 == node
.Parameters
.Count
&&
586 CompilerErrorFactory
.ValueTypesCannotDeclareParameterlessConstructors(node
));
590 !entity
.HasSelfCall
&&
591 !entity
.HasSuperCall
&&
594 IType baseType
= entity
.DeclaringType
.BaseType
;
595 IConstructor super
= GetCorrectConstructor(node
, baseType
, EmptyExpressionCollection
);
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;
634 Method closure
= CodeBuilder
.CreateMethod(
635 ClosureNameFor(node
),
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
;
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;
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
);
711 method
.Modifiers
|= TypeMemberModifiers
.Static
;
719 ProcessRegularMethod(method
);
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();
750 baseMethod
= baseProperty
.GetSetMethod();
753 if (null != baseMethod
)
755 IMethod accessorEntity
= (IMethod
)accessor
.Entity
;
756 if (TypeSystemServices
.CheckOverrideSignature(accessorEntity
, baseMethod
))
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
;
798 if (null != baseMethod
)
800 EnsureRelatedNodeWasVisited(method
, baseMethod
);
807 void ResolveMethodOverride(InternalMethod entity
)
809 IMethod baseMethod
= FindMethodOverride(entity
);
810 if (null == baseMethod
)
812 Error(CompilerErrorFactory
.NoMethodToOverride(entity
.Method
, entity
.ToString()));
816 if (!baseMethod
.IsVirtual
)
818 CantOverrideNonVirtual(entity
.Method
, baseMethod
);
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
);
835 if (baseMethod
.ReturnType
!= entity
.ReturnType
)
837 Error(CompilerErrorFactory
.InvalidOverrideReturnType(
838 entity
.Method
.ReturnType
,
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
;
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
);
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
)
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
);
993 ResolveMethodOverride(entity
);
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
);
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
);
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
);
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
);
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
;
1175 if (EntityType
.Constructor
== _currentMethod
.EntityType
)
1177 // TODO: point to super ctor
1178 node
.Entity
= _currentMethod
;
1182 if (null == _currentMethod
.Overriden
)
1185 CompilerErrorFactory
.MethodIsNotOverride(node
, _currentMethod
.ToString()));
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
))
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
);
1224 method
.ReturnType
= GetMostGenericTypeReference(entity
.ReturnExpressions
);
1226 TraceReturnType(method
, entity
);
1229 IType
MapNullToObject(IType type
)
1231 if (Null
.Default
== type
)
1233 return TypeSystemServices
.ObjectType
;
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
)
1255 type
= GetMostGenericType(type
, newType
);
1256 if (TypeSystemServices
.IsSystemObject(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
)
1278 BindExpressionType(node
, TypeSystemServices
.LongType
);
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();
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();
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);
1367 bool CheckComplexSlicingParameters(SlicingExpression node
)
1369 foreach (Slice slice
in node
.Indices
)
1371 if (!CheckComplexSlicingParameters(slice
))
1379 bool CheckComplexSlicingParameters(Slice node
)
1381 if (null != node
.Step
)
1383 NotImplemented(node
, "slicing step");
1387 if (OmittedExpression
.Default
== node
.Begin
)
1389 node
.Begin
= CreateIntegerLiteral(0);
1393 if (!AssertTypeCompatibility(node
.Begin
, TypeSystemServices
.IntType
, GetExpressionType(node
.Begin
)))
1399 if (null != node
.End
&& OmittedExpression
.Default
!= node
.End
)
1401 if (!AssertTypeCompatibility(node
.End
, TypeSystemServices
.IntType
, GetExpressionType(node
.End
)))
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
);
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
))
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));
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
);
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
);
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;
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
);
1527 CodeBuilder
.CreateAssignment(
1528 CodeBuilder
.CreateReference(temp
),
1532 CodeBuilder
.CreateMethodInvocation(
1533 CodeBuilder
.CreateReference(temp
),
1534 String_Substring_Int
,
1535 CodeBuilder
.CreateMethodInvocation(
1536 RuntimeServices_NormalizeStringIndex
,
1537 CodeBuilder
.CreateReference(temp
),
1542 mie
= CodeBuilder
.CreateMethodInvocation(node
.Target
, String_Substring_Int
, slice
.Begin
);
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
;
1559 return IsIndexedProperty(entity
);
1564 override public void LeaveSlicingExpression(SlicingExpression node
)
1566 if (IsAmbiguous(node
.Target
.Entity
))
1568 BindIndexedPropertySlicing(node
);
1573 IType targetType
= GetExpressionType(node
.Target
);
1574 if (TypeSystemServices
.IsError(targetType
))
1580 if (IsIndexedProperty(node
.Target
))
1582 BindIndexedPropertySlicing(node
);
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
);
1600 if (arrayType
.GetArrayRank() > 1)
1602 BindMultiDimensionalArraySlicing(node
);
1606 BindExpressionType(node
, arrayType
.GetElementType());
1612 if (AstUtil
.IsComplexSlicing(node
))
1614 if (TypeSystemServices
.StringType
== targetType
)
1616 BindComplexStringSlicing(node
);
1620 if (TypeSystemServices
.ListType
.IsAssignableFrom(targetType
))
1622 BindComplexListSlicing(node
);
1626 NotImplemented(node
, "complex slicing for anything but lists, arrays and strings");
1632 IEntity member
= targetType
.GetDefaultMember();
1635 Error(node
, CompilerErrorFactory
.TypeDoesNotSupportSlicing(node
.Target
, targetType
.ToString()));
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
1675 MethodInvocationExpression mie
= CodeBuilder
.CreateMethodInvocation(
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
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
;
1711 getter
= found
.GetGetMethod();
1713 else if (EntityType
.Ambiguous
== result
.EntityType
)
1719 else if (EntityType
.Property
== member
.EntityType
)
1721 getter
= ((IProperty
)member
).GetGetMethod();
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
);
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
;
1779 if (null == ge
.Filter
)
1786 NormalizeStatementModifiers
.MapStatementModifier(ge
.Filter
, out body
));
1791 body
.Add(new YieldStatement(e
.LexicalInfo
, e
));
1793 MethodInvocationExpression mie
= new MethodInvocationExpression(node
.LexicalInfo
);
1796 Node parentNode
= node
.ParentNode
;
1797 bool isGenerator
= AstUtil
.IsListMultiGenerator(parentNode
);
1798 parentNode
.Replace(node
, mie
);
1803 parentNode
.ParentNode
.Replace(
1805 CodeBuilder
.CreateConstructorInvocation(
1806 TypeSystemServices
.Map(ProcessGenerators
.List_IEnumerableConstructor
),
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
));
1818 Visit(node
.Expression
);
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
;
1854 BooClassBuilder
CreateGeneratorSkeleton(GeneratorExpression node
)
1856 BooClassBuilder builder
= CreateGeneratorSkeleton(node
, _currentMethod
.Method
, GetConcreteExpressionType(node
.Expression
));
1857 _currentMethod
.Method
.DeclaringType
.Members
.Add(builder
.ClassDefinition
);
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(
1883 TypeSystemServices
.IEnumeratorGenericType
.GenericInfo
.ConstructType(generatorItemType
));
1885 getEnumeratorBuilder
.Method
.LexicalInfo
= sourceNode
.LexicalInfo
;
1888 sourceNode
["GeneratorClassBuilder"] = builder
;
1889 sourceNode
["GetEnumeratorBuilder"] = getEnumeratorBuilder
;
1890 sourceNode
["GeneratorItemType"] = generatorItemType
;
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
);
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
);
1951 new ExpressionStatement(
1952 CodeBuilder
.CreateAssignment(
1954 CodeBuilder
.CreateReference(localInfo
),
1955 node
.Initializer
)));
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
));
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(
2042 CodeBuilder
.CreateMethodInvocation(
2049 CompilerErrorFactory
.IncompatibleExpressionType(
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
);
2084 //check if found entity can't possibly be a member of self:
2085 if (member
.DeclaringType
!= CurrentType
2086 && !(CurrentType
.IsSubclassOf(member
.DeclaringType
)))
2089 CompilerErrorFactory
.InstanceRequired(sourceNode
,
2090 member
.DeclaringType
.ToString(),
2093 target
= new SelfLiteralExpression(sourceNode
.LexicalInfo
);
2095 BindExpressionType(target
, member
.DeclaringType
);
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
);
2107 void ResolveMemberInfo(ReferenceExpression node
, IMember member
)
2109 MemberReferenceExpression memberRef
= MemberReferenceFromReference(node
, member
);
2110 Bind(memberRef
, member
);
2111 node
.ParentNode
.Replace(node
, memberRef
);
2115 override public void OnRELiteralExpression(RELiteralExpression node
)
2117 if (null != node
.Entity
)
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
);
2153 IEntity entity
= NameResolutionService
.ResolveGenericReferenceExpression(node
, node
.Target
.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
);
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
;
2191 if (IsExtensionMethod(member
))
2196 ResolveMemberInfo(node
, member
);
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
,
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
:
2230 case EntityType
.Ambiguous
:
2231 // let overload resolution deal with it
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
);
2249 case EntityType
.Ambiguous
:
2251 tag
= ResolveAmbiguousReference(node
, (Ambiguous
)tag
);
2252 IMember resolvedMember
= tag
as IMember
;
2253 if (null != resolvedMember
)
2255 ResolveMemberInfo(node
, resolvedMember
);
2260 BindTypeReferenceExpressionType(node
, (IType
)tag
);
2263 if (!AstUtil
.IsTargetOfMethodInvocation(node
)
2264 && !AstUtil
.IsTargetOfSlicing(node
)
2265 && !AstUtil
.IsLhsOfAssignment(node
))
2267 Error(node
, CompilerErrorFactory
.AmbiguousReference(
2270 ((Ambiguous
)tag
).Entities
));
2275 case EntityType
.Namespace
:
2277 if (IsStandaloneReference(node
))
2279 Error(node
, CompilerErrorFactory
.NamespaceIsNotAnExpression(node
, tag
.Name
));
2284 case EntityType
.Parameter
:
2285 case EntityType
.Local
:
2287 ILocalEntity local
= (ILocalEntity
)node
.Entity
;
2288 local
.IsUsed
= true;
2289 BindExpressionType(node
, local
.Type
);
2295 if (EntityType
.BuiltinFunction
== tag
.EntityType
)
2297 CheckBuiltinUsage(node
, tag
);
2301 if (node
.ExpressionType
== null)
2303 BindExpressionType(node
, ((ITypedEntity
)tag
).Type
);
2311 protected virtual void BindTypeReferenceExpressionType(Expression node
, IType type
)
2313 if (IsStandaloneReference(node
))
2315 BindExpressionType(node
, TypeSystemServices
.TypeType
);
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
;
2342 return GetConcreteExpressionType(target
);
2344 return (INamespace
)GetEntity(target
);
2347 protected virtual void LeaveExplodeExpression(UnaryExpression node
)
2349 IType type
= GetConcreteExpressionType(node
.Operand
);
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
))
2367 ProcessMemberReferenceExpression(node
);
2371 virtual protected void MemberNotFound(MemberReferenceExpression node
, INamespace ns
)
2373 EntityType et
= (!AstUtil
.IsTargetOfMethodInvocation(node
)) ? EntityType
.Any
: EntityType
.Method
;
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
);
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
;
2403 member
= NameResolutionService
.ResolveExtension(ns
, node
.Name
);
2404 if (null == member
) MemberNotFound(node
, ns
);
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
)
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;
2436 IMember memberInfo
= member
as IMember
;
2437 if (null != memberInfo
)
2439 if (!AssertTargetContext(node
, memberInfo
))
2445 if (EntityType
.Method
!= memberInfo
.EntityType
)
2447 BindExpressionType(node
, GetInferredType(memberInfo
));
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
),
2469 if (IsWriteOnlyProperty(property
) && !IsBeingAssignedTo(node
))
2471 Error(node
, CompilerErrorFactory
.PropertyIsWriteOnly(
2472 AstUtil
.GetMemberAnchor(node
),
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
);
2492 CompilerErrorFactory
.EventIsNotAnExpression(node
,
2499 PostProcessReferenceExpression(node
);
2502 private bool IsBeingAssignedTo(MemberReferenceExpression node
)
2504 Node current
= node
;
2505 Node parent
= current
.ParentNode
;
2506 while (!(parent
is BinaryExpression
))
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();
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
);
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
)
2569 if (!AstUtil
.IsTargetOfMethodInvocation(node
)
2570 && !AstUtil
.IsTargetOfSlicing(node
)
2571 && !AstUtil
.IsLhsOfAssignment(node
))
2573 return candidates
.Entities
[0];
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
);
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]);
2614 Bind(node
, new Ambiguous(matches
));
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
)
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
));
2682 _currentMethod
.AddYieldStatement(node
);
2686 override public void LeaveReturnStatement(ReturnStatement node
)
2688 if (null == node
.Expression
) return;
2690 // forces anonymous types to be correctly
2692 IType expressionType
= GetConcreteExpressionType(node
.Expression
);
2693 if (TypeSystemServices
.VoidType
== expressionType
2694 && node
.ContainsAnnotation(OptionalReturnStatementAnnotation
))
2696 node
.ParentNode
.Replace(
2698 new ExpressionStatement(node
.Expression
));
2702 IType returnType
= _currentMethod
.ReturnType
;
2703 if (TypeSystemServices
.IsUnknown(returnType
))
2705 _currentMethod
.AddReturnExpression(node
.Expression
);
2709 AssertTypeCompatibility(node
.Expression
, returnType
, expressionType
);
2713 protected Expression
GetCorrectIterator(Expression iterator
)
2715 IType type
= GetExpressionType(iterator
);
2716 if (TypeSystemServices
.IsError(type
))
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
);
2732 return CodeBuilder
.CreateMethodInvocation(RuntimeServices_GetEnumerable
, iterator
);
2737 IMethod method
= ResolveGetEnumerator(iterator
, type
);
2740 Error(CompilerErrorFactory
.InvalidIteratorType(iterator
, type
.ToString()));
2744 return CodeBuilder
.CreateMethodInvocation(iterator
, method
);
2751 IMethod
ResolveGetEnumerator(Node sourceNode
, IType type
)
2753 IMethod method
= ResolveMethod(type
, "GetEnumerator");
2756 EnsureRelatedNodeWasVisited(sourceNode
, method
);
2757 if (0 == method
.GetParameters().Length
&&
2758 method
.ReturnType
.IsSubclassOf(TypeSystemServices
.IEnumeratorType
))
2767 /// Process a iterator and its declarations and returns a new iterator
2768 /// expression if necessary.
2770 protected Expression
ProcessIterator(Expression iterator
, DeclarationCollection declarations
)
2772 iterator
= GetCorrectIterator(iterator
);
2773 ProcessDeclarationsForIterator(declarations
, GetExpressionType(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
);
2793 Visit(node
.OrBlock
);
2794 Visit(node
.ThenBlock
);
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
);
2821 IEntity tag
= NameResolutionService
.Resolve(d
.Name
);
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
,
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
);
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
2891 Visit(node
.FilterCondition
);
2898 // Clean up the namespace if necessary
2899 if(!anonymousException
)
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
);
2922 ExpandIncrementDecrement(node
);
2931 void ExpandIncrementDecrement(UnaryExpression node
)
2933 Node expansion
= null;
2934 if (IsArraySlicing(node
.Operand
))
2936 expansion
= ExpandIncrementDecrementArraySlicing(node
);
2940 expansion
= ExpandSimpleIncrementDecrement(node
);
2942 node
.ParentNode
.Replace(node
, expansion
);
2946 Expression
ExpandIncrementDecrementArraySlicing(UnaryExpression node
)
2948 SlicingExpression slicing
= (SlicingExpression
)node
.Operand
;
2949 CheckNoComplexSlicing(slicing
);
2951 return CreateSideEffectAwareSlicingOperation(
2953 GetEquivalentBinaryOperator(node
.Operator
),
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
),
2981 CloneOrAssignToTemp(returnValue
, lvalue
),
2983 Expression expansion
= CodeBuilder
.CreateAssignment(
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
));
3001 InternalLocal
AddInitializedTempLocal(MethodInvocationExpression eval
, Expression initializer
)
3003 InternalLocal temp
= DeclareTempLocal(GetExpressionType(initializer
));
3005 CodeBuilder
.CreateAssignment(
3006 CodeBuilder
.CreateReference(temp
),
3011 InternalLocal
DeclareOldValueTempIfNeeded(UnaryExpression node
)
3013 return AstUtil
.IsPostUnaryOperator(node
.Operator
)
3014 ? DeclareTempLocal(GetExpressionType(node
.Operand
))
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(
3033 // Resolve operator overloads if any
3034 BindArithmeticOperator(addition
);
3036 return null == oldValue
3037 ? (Expression
) assign
3038 : CodeBuilder
.CreateEvalInvocation(
3041 CodeBuilder
.CreateReference(oldValue
));
3044 Expression
CloneOrAssignToTemp(InternalLocal temp
, Expression operand
)
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
)
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
);
3090 override public void LeaveUnaryExpression(UnaryExpression node
)
3092 switch (node
.Operator
)
3094 case UnaryOperatorType
.Explode
:
3096 LeaveExplodeExpression(node
);
3099 case UnaryOperatorType
.LogicalNot
:
3101 LeaveLogicalNot(node
);
3105 case UnaryOperatorType
.Increment
:
3106 case UnaryOperatorType
.PostIncrement
:
3107 case UnaryOperatorType
.Decrement
:
3108 case UnaryOperatorType
.PostDecrement
:
3110 LeaveIncrementDecrement(node
);
3114 case UnaryOperatorType
.UnaryNegation
:
3116 LeaveUnaryNegation(node
);
3120 case UnaryOperatorType
.OnesComplement
:
3122 LeaveOnesComplement(node
);
3128 NotImplemented(node
, "unary operator not supported");
3134 private void LeaveOnesComplement(UnaryExpression node
)
3136 if (IsPrimitiveOnesComplementOperand(node
.Operand
))
3138 BindExpressionType(node
, GetExpressionType(node
.Operand
));
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
));
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
3188 ReferenceExpression reference
= (ReferenceExpression
)node
.Left
;
3189 IEntity info
= NameResolutionService
.Resolve(reference
.Name
);
3190 if (null == info
|| TypeSystemServices
.IsBuiltin(info
) || IsInaccessible(info
))
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
);
3205 bool IsInaccessible(IEntity info
)
3207 IAccessibleMember accessible
= info
as IAccessibleMember
;
3208 if (accessible
!= null && accessible
.IsPrivate
3209 && accessible
.DeclaringType
!= CurrentType
)
3216 override public void LeaveBinaryExpression(BinaryExpression node
)
3218 if (TypeSystemServices
.IsUnknown(node
.Left
) ||
3219 TypeSystemServices
.IsUnknown(node
.Right
))
3221 BindExpressionType(node
, Unknown
.Default
);
3225 if (TypeSystemServices
.IsError(node
.Left
)
3226 || TypeSystemServices
.IsError(node
.Right
))
3231 BindBinaryExpression(node
);
3234 protected virtual void BindBinaryExpression(BinaryExpression node
)
3236 if (IsEnumOperation(node
))
3238 BindEnumOperation(node
);
3242 switch (node
.Operator
)
3244 case BinaryOperatorType
.Assign
:
3246 BindAssignment(node
);
3250 case BinaryOperatorType
.Addition
:
3252 if (GetExpressionType(node
.Left
).IsArray
&&
3253 GetExpressionType(node
.Right
).IsArray
)
3255 BindArrayAddition(node
);
3259 BindArithmeticOperator(node
);
3264 case BinaryOperatorType
.Subtraction
:
3265 case BinaryOperatorType
.Multiply
:
3266 case BinaryOperatorType
.Division
:
3267 case BinaryOperatorType
.Modulus
:
3268 case BinaryOperatorType
.Exponentiation
:
3270 BindArithmeticOperator(node
);
3274 case BinaryOperatorType
.TypeTest
:
3280 case BinaryOperatorType
.ReferenceEquality
:
3282 BindReferenceEquality(node
);
3286 case BinaryOperatorType
.ReferenceInequality
:
3288 BindReferenceEquality(node
);
3292 case BinaryOperatorType
.Or
:
3293 case BinaryOperatorType
.And
:
3295 BindLogicalOperator(node
);
3299 case BinaryOperatorType
.BitwiseAnd
:
3300 case BinaryOperatorType
.BitwiseOr
:
3301 case BinaryOperatorType
.ExclusiveOr
:
3302 case BinaryOperatorType
.ShiftLeft
:
3303 case BinaryOperatorType
.ShiftRight
:
3305 BindBitwiseOperator(node
);
3309 case BinaryOperatorType
.InPlaceSubtraction
:
3310 case BinaryOperatorType
.InPlaceAddition
:
3312 BindInPlaceAddSubtract(node
);
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
);
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
);
3341 if (!ResolveOperator(node
))
3343 InvalidOperatorForTypes(node
);
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
)
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
);
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
);
3406 case BinaryOperatorType
.Subtraction
:
3409 BindExpressionType(node
, TypeSystemServices
.IntType
);
3412 else if (lhs
.IsEnum
&& !rhs
.IsEnum
)
3414 BindExpressionType(node
, lhs
);
3418 case BinaryOperatorType
.BitwiseAnd
:
3419 case BinaryOperatorType
.BitwiseOr
:
3420 case BinaryOperatorType
.ExclusiveOr
:
3423 BindExpressionType(node
, lhs
);
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
));
3446 // if (lhs.IsEnum && rhs == lhs)
3448 // BindExpressionType(node, lhs);
3452 if (!ResolveOperator(node
))
3454 InvalidOperatorForTypes(node
);
3460 bool IsChar(IType type
)
3462 return TypeSystemServices
.CharType
== type
;
3465 void BindCmpOperator(BinaryExpression node
)
3467 if (BindNullableOperation(node
))
3472 IType lhs
= GetExpressionType(node
.Left
);
3473 IType rhs
= GetExpressionType(node
.Right
);
3475 if (IsPrimitiveComparison(lhs
, rhs
))
3477 BindExpressionType(node
, TypeSystemServices
.BoolType
);
3481 if (lhs
.IsEnum
|| rhs
.IsEnum
)
3483 if (lhs
== rhs
|| IsPrimitiveNumber(rhs
) || IsPrimitiveNumber(lhs
))
3485 BindExpressionType(node
, TypeSystemServices
.BoolType
);
3489 if (!ResolveOperator(node
))
3491 InvalidOperatorForTypes(node
);
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
);
3510 Expression expression
= CreateEquals(node
);
3511 node
.ParentNode
.Replace(node
, expression
);
3515 case BinaryOperatorType
.Inequality
:
3517 if (OptimizeNullComparisons
3518 && (IsNull(node
.Left
) || IsNull(node
.Right
)))
3520 node
.Operator
= BinaryOperatorType
.ReferenceInequality
;
3521 BindReferenceEquality(node
);
3524 Expression expression
= CreateEquals(node
);
3525 Node parent
= node
.ParentNode
;
3526 parent
.Replace(node
, CodeBuilder
.CreateNotExpression(expression
));
3532 InvalidOperatorForTypes(node
);
3539 private bool IsPrimitiveComparison(IType lhs
, IType rhs
)
3541 if (IsPrimitiveNumberOrChar(lhs
) && IsPrimitiveNumberOrChar(rhs
)) return true;
3542 if (IsBool(lhs
) && IsBool(rhs
)) return true;
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
);
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)
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
))
3611 IMethod method
= null;
3612 if (node
.Operator
== BinaryOperatorType
.InPlaceAddition
)
3614 method
= eventInfo
.GetAddMethod();
3618 method
= eventInfo
.GetRemoveMethod();
3619 CallableSignature expected
= GetCallableSignature(eventInfo
.Type
);
3620 CallableSignature actual
= GetCallableSignature(node
.Right
);
3621 if (expected
!= actual
)
3624 CompilerWarningFactory
.InvalidEventUnsubscribe(
3631 MethodInvocationExpression mie
= CodeBuilder
.CreateMethodInvocation(
3632 ((MemberReferenceExpression
)node
.Left
).Target
,
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
);
3658 case BuiltinFunctionType
.AddressOf
:
3660 ProcessAddressOfInvocation(node
);
3664 case BuiltinFunctionType
.Eval
:
3666 ProcessEvalInvocation(node
);
3672 NotImplemented(node
, "BuiltinFunction: " + function
);
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
));
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
;
3702 if (TypeSystemServices
.IsIntegerNumber(GetExpressionType(args
[0])))
3704 for (int i
=1; i
<args
.Count
; ++i
)
3706 if (NodeType
.ReferenceExpression
!= args
[i
].NodeType
)
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]));
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));
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
));
3755 Error(node
, CompilerErrorFactory
.MethodReferenceExpected(arg
));
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
));
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
);
3793 if (node
.Arguments
.Count
== 1)
3795 resultingNode
= CodeBuilder
.CreateMethodInvocation(target
, Array_get_Length
);
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
);
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]);
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]);
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
);
3902 Bind(node
.Target
, member
);
3903 BindExpressionType(node
.Target
, member
.Type
);
3908 private bool TryToProcessAsExtensionInvocation(MethodInvocationExpression node
)
3910 IEntity extension
= ResolveExtension(node
);
3911 if (null == extension
) return false;
3913 ProcessExtensionMethodInvocation(node
, extension
);
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
);
3932 override public void OnMethodInvocationExpression(MethodInvocationExpression node
)
3934 if (null != node
.ExpressionType
)
3936 _context
.TraceVerbose("{0}: Method invocation already bound.", node
.LexicalInfo
);
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
))
3955 IEntity targetEntity
= node
.Target
.Entity
;
3956 if (null == targetEntity
)
3958 ProcessGenericMethodInvocation(node
);
3962 if (IsOrContainsBooExtensionMethod(targetEntity
))
3964 ProcessExtensionMethodInvocation(node
, targetEntity
);
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
);
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
);
4011 node
.ParentNode
.Replace(node
, replacement
);
4016 private System
.Collections
.Generic
.IEnumerable
<System
.Reflection
.MethodInfo
> EnumerateMetaMethods(IEntity entity
)
4018 if (entity
.EntityType
== EntityType
.Method
)
4020 yield return GetMethodInfo(entity
);
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
);
4048 private static bool IsMetaMethod(IEntity entity
)
4050 ExternalMethod m
= entity
as ExternalMethod
;
4051 if (m
== null) return false;
4055 private void ProcessMethodInvocationExpression(MethodInvocationExpression node
, IEntity targetEntity
)
4057 switch (targetEntity
.EntityType
)
4059 case EntityType
.Ambiguous
:
4061 ProcessAmbiguousMethodInvocation(node
, targetEntity
);
4064 case EntityType
.BuiltinFunction
:
4066 ProcessBuiltinInvocation((BuiltinFunction
)targetEntity
, node
);
4069 case EntityType
.Event
:
4071 ProcessEventInvocation((IEvent
)targetEntity
, node
);
4075 case EntityType
.Method
:
4077 ProcessMethodInvocation(node
, targetEntity
);
4081 case EntityType
.Constructor
:
4083 ProcessConstructorInvocation(node
, targetEntity
);
4087 case EntityType
.Type
:
4089 ProcessTypeInvocation(node
);
4093 case EntityType
.Error
:
4101 ProcessGenericMethodInvocation(node
);
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
)
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
));
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
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
);
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
;
4318 CodeBuilder
.CreateMethodInvocation(
4319 pair
.First
.LexicalInfo
,
4320 instance
.CloneNode(),
4321 member
.GetAddMethod(),
4326 case EntityType
.Field
:
4329 CodeBuilder
.CreateAssignment(
4330 pair
.First
.LexicalInfo
,
4331 CodeBuilder
.CreateMemberReference(
4332 instance
.CloneNode(),
4338 case EntityType
.Property
:
4340 IProperty property
= (IProperty
)entity
;
4341 IMethod setter
= property
.GetSetMethod();
4344 Error(CompilerErrorFactory
.PropertyIsReadOnly(
4346 property
.FullName
));
4350 //EnsureRelatedNodeWasVisited(pair.First, setter);
4352 CodeBuilder
.CreateAssignment(
4353 pair
.First
.LexicalInfo
,
4354 CodeBuilder
.CreateMemberReference(
4355 instance
.CloneNode(),
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
,
4375 BindExpressionType(node
, method
.ReturnType
);
4379 public bool EnsureInternalEventInvocation(IEvent ev
, MethodInvocationExpression node
)
4381 if (ev
.IsAbstract
|| ev
.IsVirtual
|| ev
.DeclaringType
== CurrentType
)
4384 Error(CompilerErrorFactory
.EventCanOnlyBeInvokedFromWithinDeclaringClass(node
, ev
));
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(
4397 CodeBuilder
.CreateCast(
4399 node
.Arguments
[0]));
4403 IConstructor ctor
= GetCorrectConstructor(node
, type
, node
.Arguments
);
4406 BindConstructorInvocation(node
, ctor
);
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
);
4426 if (!AssertCanCreateInstance(node
.Target
, type
))
4432 ResolveNamedArguments(type
, node
.NamedArguments
);
4433 if (type
.IsValueType
&& node
.Arguments
.Count
== 0)
4435 ProcessValueTypeInstantiation(type
, node
);
4439 IConstructor ctor
= GetCorrectConstructor(node
, type
, node
.Arguments
);
4442 BindConstructorInvocation(node
, ctor
);
4444 if (node
.NamedArguments
.Count
> 0)
4446 ReplaceTypeInvocationByEval(type
, 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
);
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
);
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
);
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
);
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
);
4563 invocation
.Arguments
.Add(CodeBuilder
.CreateObjectArray(node
.Arguments
));
4565 invocation
.NamedArguments
= node
.NamedArguments
;
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
));
4584 private bool CheckIsNotValueType(BinaryExpression node
, Expression expression
)
4586 IType tag
= GetExpressionType(expression
);
4587 if (tag
.IsValueType
)
4589 Error(CompilerErrorFactory
.OperatorCantBeUsedWithValueType(
4591 GetBinaryOperatorText(node
.Operator
),
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
);
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
)))
4634 if (slice
.Indices
.Count
> 1)
4636 if (AstUtil
.IsComplexSlicing(slice
))
4638 // FIXME: Check type compatibility
4639 BindAssignmentToComplexSliceArray(node
);
4643 if (!AssertTypeCompatibility(node
.Right
, sliceTargetType
.GetElementType(), lhsType
))
4648 BindAssignmentToSimpleSliceArray(node
);
4653 if (!AssertTypeCompatibility(node
.Right
, sliceTargetType
.GetElementType(), lhsType
))
4658 node
.ExpressionType
= sliceTargetType
.GetElementType();
4662 void BindAssignmentToSimpleSliceArray(BinaryExpression node
)
4664 SlicingExpression slice
= (SlicingExpression
)node
.Left
;
4665 MethodInvocationExpression mie
= CodeBuilder
.CreateMethodInvocation(
4667 TypeSystemServices
.Map(typeof(Array
).GetMethod("SetValue", new Type
[] { typeof(object), typeof(int[]) }
)),
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));
4693 ale
.Items
.Add(slice
.Indices
[i
].End
);
4694 collapse
.Items
.Add(new BoolLiteralExpression(false));
4698 MethodInvocationExpression mie
= CodeBuilder
.CreateMethodInvocation(
4699 RuntimeServices_SetMultiDimensionalRange1
,
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
));
4734 if (AssertParameters(node
.Left
, setMethod
, mie
.Arguments
))
4739 else if (EntityType
.Ambiguous
== lhs
.EntityType
)
4741 setter
= (IMethod
)GetCorrectCallableReference(node
.Left
, mie
.Arguments
, GetSetMethods(lhs
));
4751 Error(node
, CompilerErrorFactory
.LValueExpected(node
.Left
));
4755 mie
.Target
= CodeBuilder
.CreateMemberReference(
4756 GetIndexedPropertySlicingTarget(slice
),
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
);
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
;
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
));
4838 bool BindNullableOperation(BinaryExpression node
)
4840 if (!IsNullableOperation(node
))
4845 if (BinaryOperatorType
.ReferenceEquality
== node
.Operator
)
4847 node
.Operator
= BinaryOperatorType
.Equality
;
4849 else if (BinaryOperatorType
.ReferenceInequality
== node
.Operator
)
4851 node
.Operator
= BinaryOperatorType
.Inequality
;
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
))
4866 BindNullableInitializer(node
, node
.Right
, lhs
);
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
);
4876 Expression nil
= new BoolLiteralExpression(false);
4877 node
.Replace(node
.Right
, nil
);
4879 BindExpressionType(node
, TypeSystemServices
.BoolType
);
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
);
4893 rhs
= GetExpressionType(node
.Right
);
4894 if (TypeSystemServices
.IsNullable(rhs
))
4896 Expression val
= new MemberReferenceExpression(node
.Right
, "Value");
4897 node
.Replace(node
.Right
, val
);
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
)));
4914 mie
.Arguments
.Add(val
);
4916 node
.Replace(val
, mie
);
4920 void BindTypeTest(BinaryExpression node
)
4922 if (CheckIsNotValueType(node
, node
.Left
) &&
4923 CheckIsaArgument(node
.Right
))
4925 BindExpressionType(node
, TypeSystemServices
.BoolType
);
4933 void BindReferenceEquality(BinaryExpression node
)
4935 if (BindNullableOperation(node
))
4940 if (CheckIsNotValueType(node
, node
.Left
) &&
4941 CheckIsNotValueType(node
, node
.Right
))
4943 BindExpressionType(node
, TypeSystemServices
.BoolType
);
4951 void BindInPlaceArithmeticOperator(BinaryExpression node
)
4953 if (IsArraySlicing(node
.Left
))
4955 BindInPlaceArithmeticOperatorOnArraySlicing(node
);
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
);
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
);
4983 private void BindInPlaceArithmeticOperatorOnArraySlicing(BinaryExpression node
)
4985 Node parent
= node
.ParentNode
;
4986 Expression expansion
= CreateSideEffectAwareSlicingOperation(
4988 GetRelatedBinaryOperatorForInPlaceOperator(node
.Operator
),
4989 (SlicingExpression
) node
.Left
,
4992 parent
.Replace(node
, expansion
);
4995 BinaryOperatorType
GetRelatedBinaryOperatorForInPlaceOperator(BinaryOperatorType 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(
5035 CodeBuilder
.CreateCast(
5037 CodeBuilder
.CreateMethodInvocation(
5038 RuntimeServices_AddArrays
,
5039 CodeBuilder
.CreateTypeofExpression(lhs
.GetElementType()),
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
);
5083 bool CheckNameResolution(Node node
, string name
, IEntity tag
)
5087 Error(CompilerErrorFactory
.UnknownIdentifier(node
, name
));
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
));
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
)
5142 if (NodeType
.ReferenceExpression
!= arg
.First
.NodeType
)
5144 Error(arg
.First
, CompilerErrorFactory
.NamedParameterMustBeIdentifier(arg
));
5150 void ResolveNamedArgument(IType type
, ReferenceExpression name
, Expression
value)
5152 IMember member
= ResolvePublicFieldPropertyEvent(name
, type
, name
.Name
);
5155 NamedArgumentNotFound(type
, name
);
5159 EnsureRelatedNodeWasVisited(name
, member
);
5162 IType memberType
= member
.Type
;
5163 if (member
.EntityType
== EntityType
.Event
)
5165 AssertDelegateArgument(value, member
, GetExpressionType(value));
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
))
5186 if (!TypeSystemServices
.AreTypesRelated(expectedType
, actualType
))
5188 Error(CompilerErrorFactory
.IncompatibleExpressionType(sourceNode
, expectedType
.ToString(), actualType
.ToString()));
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()));
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)
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
]);
5231 if (!(args
[i
] is ReferenceExpression
5232 || args
[i
] is SlicingExpression
))
5234 if (reportErrors
) Error(CompilerErrorFactory
.RefArgTakesLValue(args
[i
]));
5237 if (!_callableResolution
.IsValidByRefArg(param
, parameterType
, argumentType
, args
[i
]))
5244 if (!TypeSystemServices
.AreTypesRelated(parameterType
, argumentType
))
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
)));
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
));
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
);
5351 if (!TypeSystemServices
.IsError(type
))
5353 if (null == (type
as IGenericParameter
))
5355 Error(CompilerErrorFactory
.NoApropriateConstructorFound(sourceNode
, type
.ToString(), GetSignature(arguments
)));
5359 Error(CompilerErrorFactory
.CannotCreateAnInstanceOfGenericParameterWithoutDefaultConstructorConstraint(sourceNode
, type
.ToString()));
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
);
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
));
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
)));
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
;
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
);
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
))
5449 VisitMemberForTypeResolution(node
);
5450 AssertTypeIsKnown(sourceNode
, methodEntity
, methodEntity
.ReturnType
);
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);
5471 private void VisitInParentNamespace(Node node
)
5473 INamespace saved
= NameResolutionService
.CurrentNamespace
;
5476 NameResolutionService
.EnterNamespace((INamespace
)node
.ParentNode
.Entity
);
5481 NameResolutionService
.Restore(saved
);
5486 private void AssertTypeIsKnown(Node sourceNode
, IEntity sourceEntity
, IType type
)
5488 if (TypeSystemServices
.IsUnknown(type
))
5491 CompilerErrorFactory
.UnresolvedDependency(
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
;
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
))
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
))
5541 IType rhs
= GetExpressionType(node
.Right
);
5542 if (ResolveOperator(node
, rhs
, operatorName
, mie
))
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
;
5561 if (HasOperatorSignature(method
, args
))
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
);
5582 IMethod method
= ResolveOperatorEntity(entity
, args
);
5583 if (null != method
) return method
;
5586 entity
= NameResolutionService
.ResolveExtension(type
, operatorName
);
5589 return ResolveOperatorEntity(entity
, args
);
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
))
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
);
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()));
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
;
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
);
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();
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
)
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()));
5740 Error(CompilerErrorFactory
.CantCreateInstanceOfEnum(sourceNode
, type
.ToString()));
5743 if (type
.IsAbstract
)
5745 Error(CompilerErrorFactory
.CantCreateInstanceOfAbstractType(sourceNode
, type
.ToString()));
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
));
5762 bool AssertDeclarationName(Declaration d
)
5764 if (AssertIdentifierName(d
, d
.Name
))
5766 return AssertUniqueLocal(d
);
5771 bool AssertUniqueLocal(Declaration d
)
5773 if (null == _currentMethod
.ResolveLocal(d
.Name
) &&
5774 null == _currentMethod
.ResolveParameter(d
.Name
))
5778 Error(CompilerErrorFactory
.LocalAlreadyExists(d
, d
.Name
));
5782 void GetDeclarationType(IType defaultDeclarationType
, Declaration d
)
5787 AssertTypeCompatibility(d
, GetType(d
.Type
), defaultDeclarationType
);
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
));
5839 protected virtual bool AssertLValue(Node node
, IEntity entity
)
5843 switch (entity
.EntityType
)
5845 case EntityType
.Parameter
:
5846 case EntityType
.Local
:
5851 case EntityType
.Property
:
5853 if (null == ((IProperty
)entity
).GetSetMethod())
5855 Error(CompilerErrorFactory
.PropertyIsReadOnly(AstUtil
.GetMemberAnchor(node
), entity
.FullName
));
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
));
5876 Error(CompilerErrorFactory
.LValueExpected(node
));
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
)
5907 if (AstUtil
.IsExplodeExpression(arg
))
5911 sb
.Append(GetExpressionType(arg
));
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; }