Index: src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs =================================================================== --- src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs (revision 2359) +++ src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs (working copy) @@ -1,5623 +1,5701 @@ -#region license -// Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org) -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// * Neither the name of Rodrigo B. de Oliveira nor the names of its -// contributors may be used to endorse or promote products derived from this -// software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#endregion - -using System; -using System.Collections; -using System.Diagnostics; -using System.IO; -using System.Text; -using Boo.Lang.Compiler.Ast; -using Boo.Lang.Compiler.Ast.Visitors; -using Boo.Lang.Compiler.TypeSystem; -using Boo.Lang.Runtime; -using Attribute = Boo.Lang.Compiler.Ast.Attribute; - -namespace Boo.Lang.Compiler.Steps -{ - /// - /// AST semantic evaluation. - /// - public class ProcessMethodBodies : AbstractNamespaceSensitiveVisitorCompilerStep - { - static readonly ExpressionCollection EmptyExpressionCollection = new ExpressionCollection(); - - static readonly object OptionalReturnStatementAnnotation = new object(); - - protected Stack _methodStack; - - protected Stack _memberStack; - // for accurate error reporting during type inference - - protected InternalMethod _currentMethod; - - IMethod Array_EnumerableConstructor; - - IMethod Array_TypedEnumerableConstructor; - - IMethod Array_TypedCollectionConstructor; - - IMethod Array_TypedConstructor2; - - IMethod MultiDimensionalArray_TypedConstructor; - - InfoFilter IsPublicEventFilter; - - InfoFilter IsPublicFieldPropertyEventFilter; - - protected CallableResolutionService _callableResolution; - - protected bool _optimizeNullComparisons = true; - - public ProcessMethodBodies() - { - IsPublicFieldPropertyEventFilter = new InfoFilter(IsPublicFieldPropertyEvent); - IsPublicEventFilter = new InfoFilter(IsPublicEvent); - } - - override public void Run() - { - NameResolutionService.Reset(); - - _currentMethod = null; - _methodStack = new Stack(); - _memberStack = new Stack(); - - _callableResolution = new CallableResolutionService(); - _callableResolution.Initialize(_context); - - InitializeMemberCache(); - - Visit(CompileUnit); - } - - protected IMethod ResolveMethod(IType type, string name) - { - return NameResolutionService.ResolveMethod(type, name); - } - - protected IProperty ResolveProperty(IType type, string name) - { - return NameResolutionService.ResolveProperty(type, name); - } - - virtual protected void InitializeMemberCache() - { - Array_EnumerableConstructor = TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.IEnumerable })); - Array_TypedEnumerableConstructor = TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.IEnumerable })); - Array_TypedCollectionConstructor= TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.ICollection })); - Array_TypedConstructor2 = TypeSystemServices.Map(Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.Int })); - MultiDimensionalArray_TypedConstructor = TypeSystemServices.Map(Types.Builtins.GetMethod("matrix", new Type[] { Types.Type, typeof(int[]) })); - } - - override public void Dispose() - { - base.Dispose(); - - if (null != _callableResolution) - { - _callableResolution.Dispose(); - _callableResolution = null; - } - - _currentMethod = null; - _methodStack = null; - _memberStack = null; - - _RuntimeServices_Len = null; - _RuntimeServices_Mid = null; - _RuntimeServices_NormalizeStringIndex = null; - _RuntimeServices_AddArrays = null; - _RuntimeServices_GetRange1 = null; - _RuntimeServices_GetRange2 = null; - _RuntimeServices_GetMultiDimensionalRange1 = null; - _RuntimeServices_SetMultiDimensionalRange1 = null; - _RuntimeServices_GetEnumerable = null; - _RuntimeServices_EqualityOperator = null; - _Array_get_Length = null; - _Array_GetLength = null; - _String_get_Length = null; - _String_Substring_Int = null; - _ICollection_get_Count = null; - _List_GetRange1 = null; - _List_GetRange2 = null; - _ICallable_Call = null; - _Activator_CreateInstance = null; - _ApplicationException_StringConstructor = null; - _TextReaderEnumerator_Constructor = null; - _EnumeratorItemType_Constructor = null; - } - - override public void OnModule(Module module) - { - if (WasVisited(module)) return; - MarkVisited(module); - - EnterNamespace((INamespace)TypeSystemServices.GetEntity(module)); - - Visit(module.Members); - Visit(module.AssemblyAttributes); - - LeaveNamespace(); - } - - override public void OnInterfaceDefinition(InterfaceDefinition node) - { - if (WasVisited(node)) return; - MarkVisited(node); - - VisitTypeDefinition(node); - } - - private void VisitBaseTypes(TypeDefinition node) - { - foreach (TypeReference typeRef in node.BaseTypes) - { - EnsureRelatedNodeWasVisited(typeRef, typeRef.Entity); - } - } - - private void VisitTypeDefinition(TypeDefinition node) - { - INamespace ns = (INamespace)GetEntity(node); - EnterNamespace(ns); - VisitBaseTypes(node); - Visit(node.Attributes); - Visit(node.Members); - LeaveNamespace(); - } - - override public void OnClassDefinition(ClassDefinition node) - { - if (WasVisited(node)) return; - MarkVisited(node); - - VisitTypeDefinition(node); - ProcessFieldInitializers(node); - } - - void ProcessFieldInitializers(ClassDefinition node) - { - foreach (TypeMember member in node.Members) - { - if (NodeType.Field == member.NodeType) - { - ProcessFieldInitializer((Field) member); - } - } - } - - override public void OnAttribute(Attribute node) - { - IType tag = node.Entity as IType; - if (null != tag && !TypeSystemServices.IsError(tag)) - { - Visit(node.Arguments); - ResolveNamedArguments(tag, node.NamedArguments); - - IConstructor constructor = GetCorrectConstructor(node, tag, node.Arguments); - if (null != constructor) - { - Bind(node, constructor); - } - } - } - - override public void OnProperty(Property node) - { - if (WasVisited(node)) - { - return; - } - MarkVisited(node); - - Method setter = node.Setter; - Method getter = node.Getter; - - Visit(node.Attributes); - Visit(node.Type); - Visit(node.Parameters); - - ResolvePropertyOverride(node); - - if (null != getter) - { - if (null != node.Type) - { - getter.ReturnType = node.Type.CloneNode(); - } - getter.Parameters.ExtendWithClones(node.Parameters); - - Visit(getter); - } - - IType typeInfo = null; - if (null != node.Type) - { - typeInfo = GetType(node.Type); - } - else - { - if (null != getter) - { - typeInfo = GetType(node.Getter.ReturnType); - if (typeInfo == TypeSystemServices.VoidType) - { - typeInfo = TypeSystemServices.ObjectType; - node.Getter.ReturnType = CodeBuilder.CreateTypeReference(typeInfo); - } - } - else - { - typeInfo = TypeSystemServices.ObjectType; - } - node.Type = CodeBuilder.CreateTypeReference(typeInfo); - } - - if (null != setter) - { - ParameterDeclaration parameter = new ParameterDeclaration(); - parameter.Type = CodeBuilder.CreateTypeReference(typeInfo); - parameter.Name = "value"; - parameter.Entity = new InternalParameter(parameter, node.Parameters.Count+CodeBuilder.GetFirstParameterIndex(setter)); - setter.Parameters.ExtendWithClones(node.Parameters); - setter.Parameters.Add(parameter); - setter.Name = "set_" + node.Name; - Visit(setter); - } - } - - override public void OnField(Field node) - { - if (WasVisited(node)) - { - return; - } - MarkVisited(node); - - InternalField tag = (InternalField)GetEntity(node); - - Visit(node.Attributes); - Visit(node.Type); - - if (null != node.Initializer) - { - if (tag.DeclaringType.IsValueType && !node.IsStatic) - { - Error( - CompilerErrorFactory.ValueTypeFieldsCannotHaveInitializers( - node.Initializer)); - } - try - { - PushMember(node); - PreProcessFieldInitializer(node); - } - finally - { - PopMember(); - } - } - else - { - if (null == node.Type) - { - node.Type = CodeBuilder.CreateTypeReference(TypeSystemServices.ObjectType); - node.Type.LexicalInfo = node.LexicalInfo; - } - } - CheckFieldType(node.Type); - } - - bool IsValidLiteralInitializer(Expression e) - { - switch (e.NodeType) - { - case NodeType.BoolLiteralExpression: - case NodeType.IntegerLiteralExpression: - case NodeType.DoubleLiteralExpression: - case NodeType.NullLiteralExpression: - case NodeType.StringLiteralExpression: - { - return true; - } - } - return false; - } - - void ProcessLiteralField(Field node) - { - Visit(node.Initializer); - ProcessFieldInitializerType(node, node.Initializer.ExpressionType); - ((InternalField)node.Entity).StaticValue = node.Initializer; - node.Initializer = null; - } - - void ProcessFieldInitializerType(Field node, IType initializerType) - { - if (null == node.Type) - { - node.Type = CodeBuilder.CreateTypeReference(initializerType); - node.Type.LexicalInfo = node.LexicalInfo; - } - else - { - AssertTypeCompatibility(node.Initializer, GetType(node.Type), initializerType); - } - } - - void PreProcessFieldInitializer(Field node) - { - Expression initializer = node.Initializer; - if (node.IsFinal && node.IsStatic) - { - if (IsValidLiteralInitializer(initializer)) - { - ProcessLiteralField(node); - return; - } - } - - Method method = GetFieldsInitializerMethod(node); - InternalMethod entity = (InternalMethod)method.Entity; - - ReferenceExpression temp = new ReferenceExpression("___temp_initializer"); - BinaryExpression assignment = new BinaryExpression( - node.LexicalInfo, - BinaryOperatorType.Assign, - temp, - initializer); - - ProcessNodeInMethodContext(entity, entity, assignment); - method.Locals.RemoveByEntity(temp.Entity); - - IType initializerType = ((ITypedEntity)temp.Entity).Type; - ProcessFieldInitializerType(node, initializerType); - node.Initializer = assignment.Right; - } - - void ProcessFieldInitializer(Field node) - { - Expression initializer = node.Initializer; - if (null == initializer) return; - - Method method = GetFieldsInitializerMethod(node); - method.Body.Add( - CodeBuilder.CreateAssignment( - CodeBuilder.CreateReference(node), - initializer)); - node.Initializer = null; - } - - Method CreateInitializerMethod(TypeDefinition type, string name, TypeMemberModifiers modifiers) - { - Method method = new Method(name); - method.Modifiers |= modifiers; - method.ReturnType = CodeBuilder.CreateTypeReference(TypeSystemServices.VoidType); - - InternalMethod entity = new InternalMethod(TypeSystemServices, method); - method.Entity = entity; - type.Members.Add(method); - MarkVisited(method); - return method; - } - - Method GetFieldsInitializerMethod(Field node) - { - TypeDefinition type = node.DeclaringType; - string methodName = node.IsStatic ? "___static_initializer" : "___initializer"; - Method method = (Method)type[methodName]; - if (null == method) - { - if (node.IsStatic) - { - if (null == FindStaticConstructor(type)) - { - // when the class doesnt have a static constructor - // yet, create one and use it as the static - // field initializer method - method = CreateStaticConstructor(type); - } - else - { - method = CreateInitializerMethod(type, methodName, TypeMemberModifiers.Static); - AddInitializerToStaticConstructor(type, (InternalMethod)method.Entity); - } - } - else - { - method = CreateInitializerMethod(type, methodName, TypeMemberModifiers.None); - AddInitializerToInstanceConstructors(type, (InternalMethod)method.Entity); - } - - type[methodName] = method; - } - return method; - } - - void AddInitializerToStaticConstructor(TypeDefinition type, InternalMethod initializer) - { - GetStaticConstructor(type).Body.Insert(0, - CodeBuilder.CreateMethodInvocation(initializer)); - } - - void AddInitializerToInstanceConstructors(TypeDefinition type, InternalMethod initializer) - { - foreach (TypeMember node in type.Members) - { - if (NodeType.Constructor == node.NodeType && !node.IsStatic) - { - Constructor constructor = (Constructor)node; - constructor.Body.Insert(GetIndexAfterSuperInvocation(constructor.Body), - CodeBuilder.CreateMethodInvocation( - CodeBuilder.CreateSelfReference((IType)type.Entity), - initializer)); - } - } - } - - int GetIndexAfterSuperInvocation(Block body) - { - int index = 0; - foreach (Statement s in body.Statements) - { - if (NodeType.ExpressionStatement == s.NodeType) - { - Expression expression = ((ExpressionStatement)s).Expression; - if (NodeType.MethodInvocationExpression == expression.NodeType) - { - if (NodeType.SuperLiteralExpression == ((MethodInvocationExpression)expression).Target.NodeType) - { - return index + 1; - } - } - } - ++index; - } - return 0; - } - - Constructor FindStaticConstructor(TypeDefinition type) - { - foreach (TypeMember member in type.Members) - { - if (member.IsStatic && NodeType.Constructor == member.NodeType) - { - return (Constructor)member; - } - } - return null; - } - - Constructor GetStaticConstructor(TypeDefinition type) - { - Constructor constructor = FindStaticConstructor(type); - if (null == constructor) - { - constructor = CreateStaticConstructor(type); - } - return constructor; - } - - Constructor CreateStaticConstructor(TypeDefinition type) - { - Constructor constructor = new Constructor(); - constructor.Entity = new InternalConstructor(TypeSystemServices, constructor); - constructor.Modifiers = TypeMemberModifiers.Public|TypeMemberModifiers.Static; - type.Members.Add(constructor); - MarkVisited(constructor); - return constructor; - } - - void AddFieldInitializerToStaticConstructor(int index, Field node) - { - Constructor constructor = GetStaticConstructor(node.DeclaringType); - Statement stmt = CodeBuilder.CreateFieldAssignment(node, node.Initializer); - constructor.Body.Statements.Insert(index, stmt); - node.Initializer = null; - } - - void CheckRuntimeMethod(Method method) - { - if (method.Body.Statements.Count > 0) - { - Error(CompilerErrorFactory.RuntimeMethodBodyMustBeEmpty(method, method.FullName)); - } - } - - override public void OnConstructor(Constructor node) - { - if (WasVisited(node)) - { - return; - } - MarkVisited(node); - - Visit(node.Attributes); - Visit(node.Parameters); - - InternalConstructor entity = (InternalConstructor)node.Entity; - ProcessMethodBody(entity); - - if (node.IsRuntime) - { - CheckRuntimeMethod(node); - } - else - { - if (entity.DeclaringType.IsValueType) - { - if (0 == node.Parameters.Count && - !node.IsSynthetic) - { - Error( - CompilerErrorFactory.ValueTypesCannotDeclareParameterlessConstructors(node)); - } - } - else if ( - !entity.HasSelfCall && - !entity.HasSuperCall && - !entity.IsStatic) - { - IType baseType = entity.DeclaringType.BaseType; - IConstructor super = GetCorrectConstructor(node, baseType, EmptyExpressionCollection); - if (null != super) - { - node.Body.Statements.Insert(0, - CodeBuilder.CreateSuperConstructorInvocation(super)); - } - } - } - } - - override public void LeaveParameterDeclaration(ParameterDeclaration node) - { - AssertIdentifierName(node, node.Name); - CheckParameterType(node.Type); - } - - void CheckParameterType(TypeReference type) - { - if (type.Entity != TypeSystemServices.VoidType) return; - Error(CompilerErrorFactory.InvalidParameterType(type, type.Entity.ToString())); - } - - void CheckFieldType(TypeReference type) - { - if (type.Entity != TypeSystemServices.VoidType) return; - Error(CompilerErrorFactory.InvalidFieldType(type, type.Entity.ToString())); - } - - void CheckDeclarationType(TypeReference type) - { - if (type.Entity != TypeSystemServices.VoidType) return; - Error(CompilerErrorFactory.InvalidDeclarationType(type, type.Entity.ToString())); - } - - override public void OnCallableBlockExpression(CallableBlockExpression node) - { - if (WasVisited(node)) return; - MarkVisited(node); - - TypeMemberModifiers modifiers = TypeMemberModifiers.Internal; - if (_currentMethod.IsStatic) - { - modifiers |= TypeMemberModifiers.Static; - } - - Method closure = CodeBuilder.CreateMethod( - "___closure" + _context.AllocIndex(), - Unknown.Default, - modifiers); - - MarkVisited(closure); - - InternalMethod closureEntity = (InternalMethod)closure.Entity; - - closure.LexicalInfo = node.LexicalInfo; - closure.Parameters = node.Parameters; - closure.Body = node.Body; - - _currentMethod.Method.DeclaringType.Members.Add(closure); - - CodeBuilder.BindParameterDeclarations(_currentMethod.IsStatic, closure); - - // check for invalid names and - // resolve parameter types - Visit(closure.Parameters); - - if (node.ContainsAnnotation("inline")) - { - AddOptionalReturnStatement(node.Body); - } - - // Connects the closure method namespace with the current - NamespaceDelegator ns = new NamespaceDelegator(CurrentNamespace, closureEntity); - ProcessMethodBody(closureEntity, ns); - TryToResolveReturnType(closureEntity); - - node.ExpressionType = closureEntity.Type; - node.Entity = closureEntity; - } - - private void AddOptionalReturnStatement(Block body) - { - if (body.Statements.Count != 1) return; - ExpressionStatement stmt = body.Statements[0] as ExpressionStatement; - if (null == stmt) return; - - ReturnStatement rs = new ReturnStatement(stmt.LexicalInfo, stmt.Expression, null); - rs.Annotate(OptionalReturnStatementAnnotation); - body.Replace(stmt, rs); - } - - override public void OnMethod(Method method) - { - if (WasVisited(method)) return; - MarkVisited(method); - - Visit(method.Attributes); - Visit(method.Parameters); - Visit(method.ReturnType); - Visit(method.ReturnTypeAttributes); - - bool ispinvoke = ((IMethod)GetEntity(method)).IsPInvoke; - if (method.IsRuntime || ispinvoke) - { - CheckRuntimeMethod(method); - if (ispinvoke) - { - method.Modifiers |= TypeMemberModifiers.Static; - } - } - else - { - try - { - PushMember(method); - ProcessRegularMethod(method); - } - finally - { - PopMember(); - } - } - } - - void CheckIfIsMethodOverride(InternalMethod entity) - { - if (entity.IsStatic) return; - - IMethod overriden = FindMethodOverride(entity); - if (null == overriden) return; - - ProcessMethodOverride(entity, overriden); - } - - IMethod FindPropertyAccessorOverride(Property property, Method accessor) - { - IProperty baseProperty = ((InternalProperty)property.Entity).Override; - if (null == baseProperty) return null; - - IMethod baseMethod = null; - if (property.Getter == accessor) - { - baseMethod = baseProperty.GetGetMethod(); - } - else - { - baseMethod = baseProperty.GetSetMethod(); - } - - if (null != baseMethod) - { - IMethod accessorEntity = (IMethod)accessor.Entity; - if (TypeSystemServices.CheckOverrideSignature(accessorEntity, baseMethod)) - { - return baseMethod; - } - } - - return null; - } - - IMethod FindMethodOverride(InternalMethod entity) - { - Method method = entity.Method; - if (NodeType.Property == method.ParentNode.NodeType) - { - return FindPropertyAccessorOverride((Property)method.ParentNode, method); - } - - IType baseType = entity.DeclaringType.BaseType; - IEntity candidates = NameResolutionService.Resolve(baseType, entity.Name, EntityType.Method); - if (null != candidates) - { - IMethod baseMethod = null; - if (EntityType.Method == candidates.EntityType) - { - IMethod candidate = (IMethod)candidates; - if (TypeSystemServices.CheckOverrideSignature(entity, candidate)) - { - baseMethod = candidate; - } - } - else if (EntityType.Ambiguous == candidates.EntityType) - { - IEntity[] entities = ((Ambiguous)candidates).Entities; - foreach (IMethod candidate in entities) - { - if (TypeSystemServices.CheckOverrideSignature(entity, candidate)) - { - baseMethod = candidate; - break; - } - } - } - if (null != baseMethod) - { - EnsureRelatedNodeWasVisited(method, baseMethod); - } - return baseMethod; - } - return null; - } - - void ResolveMethodOverride(InternalMethod entity) - { - IMethod baseMethod = FindMethodOverride(entity); - if (null == baseMethod) - { - Error(CompilerErrorFactory.NoMethodToOverride(entity.Method, entity.ToString())); - } - else - { - if (!baseMethod.IsVirtual) - { - CantOverrideNonVirtual(entity.Method, baseMethod); - } - else - { - ProcessMethodOverride(entity, baseMethod); - } - } - } - - void ProcessMethodOverride(InternalMethod entity, IMethod baseMethod) - { - if (TypeSystemServices.IsUnknown(entity.ReturnType)) - { - entity.Method.ReturnType = CodeBuilder.CreateTypeReference(baseMethod.ReturnType); - } - else - { - if (baseMethod.ReturnType != entity.ReturnType) - { - Error(CompilerErrorFactory.InvalidOverrideReturnType( - entity.Method.ReturnType, - baseMethod.FullName, - baseMethod.ReturnType.ToString(), - entity.ReturnType.ToString())); - } - } - SetOverride(entity, baseMethod); - } - - void CantOverrideNonVirtual(Method method, IMethod baseMethod) - { - Error(CompilerErrorFactory.CantOverrideNonVirtual(method, baseMethod.ToString())); - } - - void SetPropertyAccessorOverride(Method accessor) - { - if (null != accessor) - { - accessor.Modifiers |= TypeMemberModifiers.Override; - } - } - - IProperty ResolvePropertyOverride(IProperty p, IEntity[] candidates) - { - foreach (IEntity candidate in candidates) - { - if (EntityType.Property != candidate.EntityType) continue; - IProperty candidateProperty = (IProperty)candidate; - if (CheckOverrideSignature(p, candidateProperty)) - { - return candidateProperty; - } - } - return null; - } - - bool CheckOverrideSignature(IProperty p, IProperty candidate) - { - return TypeSystemServices.CheckOverrideSignature(p.GetParameters(), candidate.GetParameters()); - } - - void ResolvePropertyOverride(Property property) - { - InternalProperty entity = (InternalProperty)property.Entity; - IType baseType = entity.DeclaringType.BaseType; - IEntity baseProperties = NameResolutionService.Resolve(baseType, property.Name, EntityType.Property); - if (null != baseProperties) - { - if (EntityType.Property == baseProperties.EntityType) - { - IProperty candidate = (IProperty)baseProperties; - if (CheckOverrideSignature(entity, candidate)) - { - entity.Override = candidate; - } - } - else if (EntityType.Ambiguous == baseProperties.EntityType) - { - entity.Override = ResolvePropertyOverride(entity, ((Ambiguous)baseProperties).Entities); - } - } - - if (null != entity.Override) - { - EnsureRelatedNodeWasVisited(property, entity.Override); - if (property.IsOverride) - { - SetPropertyAccessorOverride(property.Getter); - SetPropertyAccessorOverride(property.Setter); - } - else - { - if (null != entity.Override.GetGetMethod()) - { - SetPropertyAccessorOverride(property.Getter); - } - if (null != entity.Override.GetSetMethod()) - { - SetPropertyAccessorOverride(property.Setter); - } - } - - if (null == property.Type) - { - property.Type = CodeBuilder.CreateTypeReference(entity.Override.Type); - } - } - } - - void SetOverride(InternalMethod entity, IMethod baseMethod) - { - TraceOverride(entity.Method, baseMethod); - - entity.Overriden = baseMethod; - entity.Method.Modifiers |= TypeMemberModifiers.Override; - } - - - void TraceOverride(Method method, IMethod baseMethod) - { - _context.TraceInfo("{0}: Method '{1}' overrides '{2}'", method.LexicalInfo, method.Name, baseMethod); - } - - class ReturnExpressionFinder : DepthFirstVisitor - { - bool _hasReturnStatements = false; - - bool _hasYieldStatements = false; - - public ReturnExpressionFinder(Method node) - { - Visit(node.Body); - } - - public bool HasReturnStatements - { - get - { - return _hasReturnStatements; - } - } - - public bool HasYieldStatements - { - get - { - return _hasYieldStatements; - } - } - - public override void OnReturnStatement(ReturnStatement node) - { - _hasReturnStatements |= (null != node.Expression); - } - - public override void OnYieldStatement(YieldStatement node) - { - _hasYieldStatements = true; - } - } - - bool DontHaveReturnExpressionsNorYield(Method node) - { - ReturnExpressionFinder finder = new ReturnExpressionFinder(node); - return !(finder.HasReturnStatements || finder.HasYieldStatements); - } - - void PreProcessMethod(Method node) - { - if (WasAlreadyPreProcessed(node)) return; - MarkPreProcessed(node); - - InternalMethod entity = (InternalMethod)GetEntity(node); - if (node.IsOverride) - { - ResolveMethodOverride(entity); - } - else - { - CheckIfIsMethodOverride(entity); - if (TypeSystemServices.IsUnknown(entity.ReturnType)) - { - if (DontHaveReturnExpressionsNorYield(node)) - { - node.ReturnType = CodeBuilder.CreateTypeReference(TypeSystemServices.VoidType); - } - } - } - } - - static readonly object PreProcessedKey = new object(); - - private bool WasAlreadyPreProcessed(Method node) - { - return node.ContainsAnnotation(PreProcessedKey); - } - - private void MarkPreProcessed(Method node) - { - node[PreProcessedKey] = PreProcessedKey; - } - - void ProcessRegularMethod(Method node) - { - PreProcessMethod(node); - - InternalMethod entity = (InternalMethod)GetEntity(node); - ProcessMethodBody(entity); - - bool parentIsClass = node.DeclaringType.NodeType == NodeType.ClassDefinition; - if (parentIsClass) - { - if (TypeSystemServices.IsUnknown(entity.ReturnType)) - { - TryToResolveReturnType(entity); - } - else - { - if (entity.IsGenerator) - { - CheckGeneratorReturnType(node, entity.ReturnType); - } - } - CheckGeneratorCantReturnValues(entity); - } - } - - void CheckGeneratorCantReturnValues(InternalMethod entity) - { - if (entity.IsGenerator && null != entity.ReturnExpressions) - { - foreach (Expression e in entity.ReturnExpressions) - { - Error(CompilerErrorFactory.GeneratorCantReturnValue(e)); - } - } - } - - void CheckGeneratorReturnType(Method method, IType returnType) - { - if (TypeSystemServices.IEnumerableType != returnType && - TypeSystemServices.IEnumeratorType != returnType && - !TypeSystemServices.IsSystemObject(returnType)) - { - Error(CompilerErrorFactory.InvalidGeneratorReturnType(method.ReturnType)); - } - } - - void ProcessMethodBody(InternalMethod entity) - { - ProcessMethodBody(entity, entity); - } - - void ProcessMethodBody(InternalMethod entity, INamespace ns) - { - ProcessNodeInMethodContext(entity, ns, entity.Method.Body); - if (entity.IsGenerator) - { - CreateGeneratorSkeleton(entity); - } - } - - void ProcessNodeInMethodContext(InternalMethod entity, INamespace ns, Node node) - { - PushMethodInfo(entity); - EnterNamespace(ns); - try - { - Visit(node); - } - finally - { - LeaveNamespace(); - PopMethodInfo(); - } - } - - void ResolveGeneratorReturnType(InternalMethod entity) - { - Method method = entity.Method; - BooClassBuilder generatorType = (BooClassBuilder)method["GeneratorClassBuilder"]; - method.ReturnType = CodeBuilder.CreateTypeReference(generatorType.Entity); - } - - void TryToResolveReturnType(InternalMethod tag) - { - if (tag.IsGenerator) - { - ResolveGeneratorReturnType(tag); - } - else - { - if (CanResolveReturnType(tag)) - { - ResolveReturnType(tag); - } - } - } - - override public void OnSuperLiteralExpression(SuperLiteralExpression node) - { - node.Entity = _currentMethod; - node.ExpressionType = _currentMethod.DeclaringType.BaseType; - - if (!AstUtil.IsTargetOfMethodInvocation(node)) return; - if (EntityType.Constructor == _currentMethod.EntityType) return; - if (null != _currentMethod.Overriden) return; - - Error( - CompilerErrorFactory.MethodIsNotOverride(node, _currentMethod.ToString())); - } - - bool CanResolveReturnType(InternalMethod tag) - { - ExpressionCollection expressions = tag.ReturnExpressions; - if (null != expressions) - { - foreach (Expression expression in expressions) - { - IType type = expression.ExpressionType; - if (null == type || TypeSystemServices.IsUnknown(type)) - { - return false; - } - } - } - return true; - } - - TypeReference GetMostGenericTypeReference(ExpressionCollection expressions) - { - IType type = MapNullToObject(GetMostGenericType(expressions)); - return CodeBuilder.CreateTypeReference(type); - } - - void ResolveReturnType(InternalMethod entity) - { - Method method = entity.Method; - if (null == entity.ReturnExpressions) - { - method.ReturnType = CodeBuilder.CreateTypeReference(TypeSystemServices.VoidType); - } - else - { - method.ReturnType = GetMostGenericTypeReference(entity.ReturnExpressions); - } - TraceReturnType(method, entity); - } - - IType MapNullToObject(IType type) - { - if (Null.Default == type) - { - return TypeSystemServices.ObjectType; - } - return type; - } - - IType GetMostGenericType(IType lhs, IType rhs) - { - return TypeSystemServices.GetMostGenericType(lhs, rhs); - } - - IType GetMostGenericType(ExpressionCollection args) - { - IType type = GetConcreteExpressionType(args[0]); - for (int i=1; i 1) - { - IArrayType arrayType = (IArrayType)GetExpressionType(node.Target); - MethodInvocationExpression mie = null; - ArrayLiteralExpression collapse = new ArrayLiteralExpression(); - ArrayLiteralExpression ranges = new ArrayLiteralExpression(); - int collapseCount = 0; - for (int i = 0; i < node.Indices.Count; i++) - { - ranges.Items.Add(node.Indices[i].Begin); - if (node.Indices[i].End == null || - node.Indices[i].End == OmittedExpression.Default) - { - BinaryExpression end = new BinaryExpression(BinaryOperatorType.Addition, - node.Indices[i].Begin, - new IntegerLiteralExpression(1)); - ranges.Items.Add(end); - BindExpressionType(end, GetExpressionType(node.Indices[i].Begin)); - collapse.Items.Add(new BoolLiteralExpression(true)); - collapseCount++; - } - else - { - ranges.Items.Add(node.Indices[i].End); - collapse.Items.Add(new BoolLiteralExpression(false)); - } - } - mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetMultiDimensionalRange1, node.Target, ranges); - mie.Arguments.Add(collapse); - - BindExpressionType(ranges, TypeSystemServices.Map(typeof(int[]))); - BindExpressionType(collapse, TypeSystemServices.Map(typeof(bool[]))); - BindExpressionType(mie, TypeSystemServices.GetArrayType(arrayType.GetElementType(), node.Indices.Count - collapseCount)); - node.ParentNode.Replace(node, mie); - } - else - { - Slice slice = node.Indices[0]; - - if (CheckComplexSlicingParameters(slice)) - { - MethodInvocationExpression mie = null; - - if (null == slice.End || slice.End == OmittedExpression.Default) - { - mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetRange1, node.Target, slice.Begin); - } - else - { - mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_GetRange2, node.Target, slice.Begin, slice.End); - } - - BindExpressionType(mie, GetExpressionType(node.Target)); - node.ParentNode.Replace(node, mie); - } - } - } - } - - bool NeedsNormalization(Expression index) - { - if (NodeType.IntegerLiteralExpression == index.NodeType) - { - return ((IntegerLiteralExpression)index).Value < 0; - } - return true; - } - - void BindComplexStringSlicing(SlicingExpression node) - { - Slice slice = node.Indices[0]; - - if (CheckComplexSlicingParameters(slice)) - { - MethodInvocationExpression mie = null; - - if (null == slice.End || slice.End == OmittedExpression.Default) - { - if (NeedsNormalization(slice.Begin)) - { - mie = CodeBuilder.CreateEvalInvocation(node.LexicalInfo); - mie.ExpressionType = TypeSystemServices.StringType; - - InternalLocal temp = DeclareTempLocal(TypeSystemServices.StringType); - mie.Arguments.Add( - CodeBuilder.CreateAssignment( - CodeBuilder.CreateReference(temp), - node.Target)); - - mie.Arguments.Add( - CodeBuilder.CreateMethodInvocation( - CodeBuilder.CreateReference(temp), - String_Substring_Int, - CodeBuilder.CreateMethodInvocation( - RuntimeServices_NormalizeStringIndex, - CodeBuilder.CreateReference(temp), - slice.Begin))); - } - else - { - mie = CodeBuilder.CreateMethodInvocation(node.Target, String_Substring_Int, slice.Begin); - } - } - else - { - mie = CodeBuilder.CreateMethodInvocation(RuntimeServices_Mid, node.Target, slice.Begin, slice.End); - } - - node.ParentNode.Replace(node, mie); - } - } - - bool IsIndexedProperty(Expression expression) - { - IEntity entity = expression.Entity; - if (null != entity) - { - return IsIndexedProperty(entity); - } - return false; - } - - override public void LeaveSlicingExpression(SlicingExpression node) - { - if (IsAmbiguous(node.Target.Entity)) - { - BindIndexedPropertySlicing(node); - return; - } - - // target[indices] - IType targetType = GetExpressionType(node.Target); - if (TypeSystemServices.IsError(targetType)) - { - Error(node); - return; - } - - if (IsIndexedProperty(node.Target)) - { - BindIndexedPropertySlicing(node); - } - else - { - if (targetType.IsArray) - { - IArrayType arrayType = (IArrayType)targetType; - if (arrayType.GetArrayRank() != node.Indices.Count) - { - Error(node, CompilerErrorFactory.InvalidArrayRank(node, node.Target.ToString(), arrayType.GetArrayRank(), node.Indices.Count)); - } - - if (AstUtil.IsComplexSlicing(node)) - { - BindComplexArraySlicing(node); - } - else - { - if (arrayType.GetArrayRank() > 1) - { - BindMultiDimensionalArraySlicing(node); - } - else - { - BindExpressionType(node, arrayType.GetElementType()); - } - } - } - else - { - if (AstUtil.IsComplexSlicing(node)) - { - if (TypeSystemServices.StringType == targetType) - { - BindComplexStringSlicing(node); - } - else - { - if (TypeSystemServices.ListType.IsAssignableFrom(targetType)) - { - BindComplexListSlicing(node); - } - else - { - NotImplemented(node, "complex slicing for anything but lists, arrays and strings"); - } - } - } - else - { - IEntity member = targetType.GetDefaultMember(); - if (null == member) - { - Error(node, CompilerErrorFactory.TypeDoesNotSupportSlicing(node.Target, targetType.ToString())); - } - else - { - node.Target = new MemberReferenceExpression(node.LexicalInfo, node.Target, member.Name); - node.Target.Entity = member; - // to be resolved later - node.Target.ExpressionType = Null.Default; - SliceMember(node, member); - } - } - } - } - } - - private void BindIndexedPropertySlicing(SlicingExpression node) - { - CheckNoComplexSlicing(node); - SliceMember(node, node.Target.Entity); - } - - private bool IsAmbiguous(IEntity entity) - { - return null != entity && EntityType.Ambiguous == entity.EntityType; - } - - bool IsIndexedProperty(IEntity tag) - { - return EntityType.Property == tag.EntityType && - ((IProperty)tag).GetParameters().Length > 0; - } - - void BindMultiDimensionalArraySlicing(SlicingExpression node) - { - if (AstUtil.IsLhsOfAssignment(node)) - { - // leave it to LeaveBinaryExpression to resolve - return; - } - - MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation( - node.Target, - TypeSystemServices.Map( - typeof(Array).GetMethod("GetValue", new Type[] { typeof(int[]) }))); - for (int i = 0; i < node.Indices.Count; i++) - { - mie.Arguments.Add(node.Indices[i].Begin); - } - - IType elementType = node.Target.ExpressionType.GetElementType(); - node.ParentNode.Replace(node, CodeBuilder.CreateCast(elementType, mie)); - } - - void SliceMember(SlicingExpression node, IEntity member) - { - EnsureRelatedNodeWasVisited(node, member); - if (AstUtil.IsLhsOfAssignment(node)) - { - // leave it to LeaveBinaryExpression to resolve - Bind(node, member); - return; - } - - MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo); - foreach (Slice index in node.Indices) - { - mie.Arguments.Add(index.Begin); - } - - IMethod getter = null; - if (EntityType.Ambiguous == member.EntityType) - { - IEntity result = ResolveAmbiguousPropertyReference((ReferenceExpression)node.Target, (Ambiguous)member, mie.Arguments); - IProperty found = result as IProperty; - if (null != found) - { - getter = found.GetGetMethod(); - } - else if (EntityType.Ambiguous == result.EntityType) - { - Error(node); - return; - } - } - else if (EntityType.Property == member.EntityType) - { - getter = ((IProperty)member).GetGetMethod(); - } - - if (null != getter) - { - if (AssertParameters(node, getter, mie.Arguments)) - { - Expression target = GetIndexedPropertySlicingTarget(node); - - mie.Target = CodeBuilder.CreateMemberReference(target, getter); - BindExpressionType(mie, getter.ReturnType); - - node.ParentNode.Replace(node, mie); - } - else - { - Error(node); - } - } - else - { - NotImplemented(node, "slice for anything but arrays and default properties"); - } - } - - private Expression GetIndexedPropertySlicingTarget(SlicingExpression node) - { - Expression target = node.Target; - MemberReferenceExpression mre = target as MemberReferenceExpression; - if (null != mre) return mre.Target; - return CodeBuilder.CreateSelfReference(this.CurrentType); - } - - override public void LeaveExpressionInterpolationExpression(ExpressionInterpolationExpression node) - { - BindExpressionType(node, TypeSystemServices.StringType); - } - - override public void LeaveListLiteralExpression(ListLiteralExpression node) - { - BindExpressionType(node, TypeSystemServices.ListType); - TypeSystemServices.MapToConcreteExpressionTypes(node.Items); - } - - override public void OnExtendedGeneratorExpression(ExtendedGeneratorExpression node) - { - CallableBlockExpression block = new CallableBlockExpression(node.LexicalInfo); - - Block body = block.Body; - Expression e = node.Items[0].Expression; - foreach (GeneratorExpression ge in node.Items) - { - ForStatement fs = new ForStatement(ge.LexicalInfo); - fs.Iterator = ge.Iterator; - fs.Declarations = ge.Declarations; - - body.Add(fs); - - if (null == ge.Filter) - { - body = fs.Block; - } - else - { - fs.Block.Add( - NormalizeStatementModifiers.MapStatementModifier(ge.Filter, out body)); - } - - - } - body.Add(new YieldStatement(e.LexicalInfo, e)); - - MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo); - mie.Target = block; - - Node parentNode = node.ParentNode; - bool isGenerator = AstUtil.IsListMultiGenerator(parentNode); - parentNode.Replace(node, mie); - mie.Accept(this); - - if (isGenerator) - { - parentNode.ParentNode.Replace( - parentNode, - CodeBuilder.CreateConstructorInvocation( - TypeSystemServices.Map(ProcessGenerators.List_IEnumerableConstructor), - mie)); - } - } - - override public void OnGeneratorExpression(GeneratorExpression node) - { - Visit(node.Iterator); - node.Iterator = ProcessIterator(node.Iterator, node.Declarations); - - EnterNamespace(new DeclarationsNamespace(CurrentNamespace, TypeSystemServices, node.Declarations)); - Visit(node.Filter); - Visit(node.Expression); - LeaveNamespace(); - - BooClassBuilder generatorType = CreateGeneratorSkeleton(node); - - BindExpressionType(node, generatorType.Entity); - } - - void CreateGeneratorSkeleton(InternalMethod entity) - { - Method method = entity.Method; - ExpressionCollection yieldExpressions = entity.YieldExpressions; - IType itemType = yieldExpressions.Count > 0 - ? GetMostGenericType(yieldExpressions) - : TypeSystemServices.ObjectType; - BooClassBuilder builder = CreateGeneratorSkeleton(method, method, itemType); - TypeSystemServices.AddCompilerGeneratedType(builder.ClassDefinition); - } - - BooClassBuilder CreateGeneratorSkeleton(GeneratorExpression node) - { - BooClassBuilder builder = CreateGeneratorSkeleton(node, _currentMethod.Method, GetConcreteExpressionType(node.Expression)); - _currentMethod.Method.DeclaringType.Members.Add(builder.ClassDefinition); - return builder; - } - - BooClassBuilder CreateGeneratorSkeleton(Node sourceNode, Method method, IType generatorItemType) - { - // create the class skeleton for type inference to work - BooClassBuilder builder = CodeBuilder.CreateClass( - string.Format("{0}___generator{1}", method.Name, _context.AllocIndex()), - TypeMemberModifiers.Private|TypeMemberModifiers.Final); - builder.LexicalInfo = sourceNode.LexicalInfo; - builder.AddBaseType(TypeSystemServices.Map(typeof(AbstractGenerator))); - builder.AddAttribute(CodeBuilder.CreateAttribute( - EnumeratorItemType_Constructor, - CodeBuilder.CreateTypeofExpression(generatorItemType))); - - BooMethodBuilder getEnumeratorBuilder = builder.AddVirtualMethod("GetEnumerator", TypeSystemServices.IEnumeratorType); - getEnumeratorBuilder.Method.LexicalInfo = sourceNode.LexicalInfo; - sourceNode["GeneratorClassBuilder"] = builder; - sourceNode["GetEnumeratorBuilder"] = getEnumeratorBuilder; - sourceNode["GeneratorItemType"] = generatorItemType; - - return builder; - } - - override public void LeaveHashLiteralExpression(HashLiteralExpression node) - { - BindExpressionType(node, TypeSystemServices.HashType); - foreach (ExpressionPair pair in node.Items) - { - GetConcreteExpressionType(pair.First); - GetConcreteExpressionType(pair.Second); - } - } - - override public void LeaveArrayLiteralExpression(ArrayLiteralExpression node) - { - TypeSystemServices.MapToConcreteExpressionTypes(node.Items); - IArrayType type = InferArrayType(node); - BindExpressionType(node, type); - if (null == node.Type) - { - node.Type = (ArrayTypeReference)CodeBuilder.CreateTypeReference(type); - } - else - { - CheckItems(type.GetElementType(), node.Items); - } - } - - private IArrayType InferArrayType(ArrayLiteralExpression node) - { - if (null != node.Type) return (IArrayType)node.Type.Entity; - if (0 == node.Items.Count) return TypeSystemServices.ObjectArrayType; - return TypeSystemServices.GetArrayType(GetMostGenericType(node.Items), 1); - } - - override public void LeaveDeclaration(Declaration node) - { - if (null == node.Type) return; - CheckDeclarationType(node.Type); - } - - override public void LeaveDeclarationStatement(DeclarationStatement node) - { - IType type = TypeSystemServices.ObjectType; - if (null != node.Declaration.Type) - { - type = GetType(node.Declaration.Type); - } - else if (null != node.Initializer) - { - // The boo syntax does not require this check because - // there's no way to create an untyped declaration statement. - // This is here to support languages that do allow untyped variable - // declarations (unityscript is such an example). - type = GetExpressionType(node.Initializer); - } - - AssertDeclarationName(node.Declaration); - - IEntity localInfo = DeclareLocal(node, node.Declaration.Name, type); - if (null != node.Initializer) - { - AssertTypeCompatibility(node.Initializer, type, GetExpressionType(node.Initializer)); - - node.ReplaceBy( - new ExpressionStatement( - CodeBuilder.CreateAssignment( - node.LexicalInfo, - CodeBuilder.CreateReference(localInfo), - node.Initializer))); - } - else - { - node.ReplaceBy( - new ExpressionStatement( - CreateDefaultLocalInitializer(node, localInfo))); - } - } - - virtual protected Expression CreateDefaultLocalInitializer(Node sourceNode, IEntity local) - { - return CodeBuilder.CreateDefaultInitializer( - sourceNode.LexicalInfo, - (InternalLocal)local); - } - - override public void LeaveExpressionStatement(ExpressionStatement node) - { - AssertHasSideEffect(node.Expression); - } - - override public void OnNullLiteralExpression(NullLiteralExpression node) - { - BindExpressionType(node, Null.Default); - } - - override public void OnSelfLiteralExpression(SelfLiteralExpression node) - { - if (null == _currentMethod) - { - Error(node, CompilerErrorFactory.SelfOutsideMethod(node)); - } - else - { - if (_currentMethod.IsStatic) - { - if (NodeType.MemberReferenceExpression != node.ParentNode.NodeType) - { - // if we are inside a MemberReferenceExpression - // let the MemberReferenceExpression deal with it - // as it can provide a better message - Error(CompilerErrorFactory.ObjectRequired(node)); - } - } - node.Entity = _currentMethod; - node.ExpressionType = _currentMethod.DeclaringType; - } - } - - override public void LeaveTypeofExpression(TypeofExpression node) - { - BindExpressionType(node, TypeSystemServices.TypeType); - } - - override public void LeaveCastExpression(CastExpression node) - { - IType fromType = GetExpressionType(node.Target); - IType toType = GetType(node.Type); - if (!TypeSystemServices.AreTypesRelated(toType, fromType) && - !(toType.IsInterface && !fromType.IsFinal) && - !(TypeSystemServices.IsIntegerNumber(toType) && TypeSystemServices.CanBeExplicitlyCastToInteger(fromType)) && - !(TypeSystemServices.IsIntegerNumber(fromType) && TypeSystemServices.CanBeExplicitlyCastToInteger(toType))) - { - IMethod explicitOperator = TypeSystemServices.FindExplicitConversionOperator(fromType, toType); - if (null != explicitOperator) - { - node.ParentNode.Replace( - node, - CodeBuilder.CreateMethodInvocation( - explicitOperator, - node.Target)); - return; - } - - Error( - CompilerErrorFactory.IncompatibleExpressionType( - node, - toType.ToString(), - fromType.ToString())); - } - BindExpressionType(node, toType); - } - - override public void LeaveTryCastExpression(TryCastExpression node) - { - IType target = GetExpressionType(node.Target); - IType toType = GetType(node.Type); - - if (target.IsValueType) - { - Error(CompilerErrorFactory.CantCastToValueType(node.Target, target.ToString())); - } - else if (toType.IsValueType) - { - Error(CompilerErrorFactory.CantCastToValueType(node.Type, toType.ToString())); - } - BindExpressionType(node, toType); - } - - protected Expression CreateMemberReferenceTarget(Node sourceNode, IMember member) - { - Expression target = null; - - if (member.IsStatic) - { - target = new ReferenceExpression(sourceNode.LexicalInfo, member.DeclaringType.FullName); - Bind(target, member.DeclaringType); - } - else - { - //check if found entity can't possibly be a member of self: - if (member.DeclaringType != CurrentType - && !(CurrentType.IsSubclassOf(member.DeclaringType))) - { - Error( - CompilerErrorFactory.InstanceRequired(sourceNode, - member.DeclaringType.ToString(), - member.Name)); - } - target = new SelfLiteralExpression(sourceNode.LexicalInfo); - } - BindExpressionType(target, member.DeclaringType); - return target; - } - - protected MemberReferenceExpression MemberReferenceFromReference(ReferenceExpression node, IMember member) - { - MemberReferenceExpression memberRef = new MemberReferenceExpression(node.LexicalInfo); - memberRef.Name = node.Name; - memberRef.Target = CreateMemberReferenceTarget(node, member); - return memberRef; - } - - void ResolveMemberInfo(ReferenceExpression node, IMember member) - { - MemberReferenceExpression memberRef = MemberReferenceFromReference(node, member); - Bind(memberRef, member); - node.ParentNode.Replace(node, memberRef); - Visit(memberRef); - } - - override public void OnRELiteralExpression(RELiteralExpression node) - { - if (null != node.Entity) - { - return; - } - - IType type = TypeSystemServices.RegexType; - BindExpressionType(node, type); - - if (NodeType.Field != node.ParentNode.NodeType) - { - ReplaceByStaticFieldReference(node, "___re" + _context.AllocIndex(), type); - } - } - - void ReplaceByStaticFieldReference(Expression node, string fieldName, IType type) - { - Node parent = node.ParentNode; - - Field field = new Field(node.LexicalInfo); - field.Name = fieldName; - field.Type = CodeBuilder.CreateTypeReference(type); - field.Modifiers = TypeMemberModifiers.Private|TypeMemberModifiers.Static; - field.Initializer = node; - - _currentMethod.Method.DeclaringType.Members.Add(field); - InternalField tag = new InternalField(field); - Bind(field, tag); - - AddFieldInitializerToStaticConstructor(0, field); - - parent.Replace(node, CodeBuilder.CreateMemberReference( - CodeBuilder.CreateReference(node.LexicalInfo, _currentMethod.DeclaringType), - tag)); - } - - override public void LeaveGenericReferenceExpression(GenericReferenceExpression node) - { - CompilerError error = CheckGenericReferenceExpression(node); - if (null != error) - { - Error(node, error); - return; - } - - IType genericType = ((IType)node.Target.Entity).GenericTypeDefinitionInfo.MakeGenericType(GetGenericArguments(node)); - Bind(node, genericType); - BindExpressionType(node, this.TypeSystemServices.TypeType); - - } - - private IType[] GetGenericArguments(GenericReferenceExpression node) - { - IType[] types = new IType[node.GenericArguments.Count]; - for (int i = 0; i < node.GenericArguments.Count; ++i) - { - IType type = node.GenericArguments[i].Entity as IType; - types[i] = type; - } - return types; - } - - CompilerError CheckGenericReferenceExpression(GenericReferenceExpression node) - { - IEntity entity = node.Target.Entity; - IType type = entity as IType; - if (type == null || type.GenericTypeDefinitionInfo == null) - { - return CompilerErrorFactory.NotAGenericDefinition(AstUtil.GetMemberAnchor(node.Target), entity.FullName); - } - - IGenericParameter[] parameters = type.GenericTypeDefinitionInfo.GenericParameters; - if (parameters.Length != node.GenericArguments.Count) return CompilerErrorFactory.GenericDefinitionArgumentCount(AstUtil.GetMemberAnchor(node.Target), entity.FullName, parameters.Length); - - return null; - } - - override public void OnReferenceExpression(ReferenceExpression node) - { - if (null != node.ExpressionType) - { - return; - } - - IEntity entity = ResolveName(node, node.Name); - if (null != entity) - { - // BOO-314 - if we are trying to invoke - // something, let's make sure it is - // something callable, otherwise, let's - // try to find something callable - if (AstUtil.IsTargetOfMethodInvocation(node) - && !IsCallableEntity(entity)) - { - IEntity callable = ResolveCallable(node); - if (null != callable) entity = callable; - } - - IMember member = entity as IMember; - if (null != member) - { - ResolveMemberInfo(node, member); - } - else - { - EnsureRelatedNodeWasVisited(node, entity); - node.Entity = entity; - PostProcessReferenceExpression(node); - } - } - else - { - Error(node); - } - } - - private IEntity ResolveCallable(ReferenceExpression node) - { - return NameResolutionService.Resolve(node.Name, - EntityType.Type - | EntityType.Method - | EntityType.BuiltinFunction - | EntityType.Event); - } - - private bool IsCallableEntity(IEntity entity) - { - switch (entity.EntityType) - { - case EntityType.Method: - case EntityType.Type: - case EntityType.Event: - case EntityType.BuiltinFunction: - case EntityType.Constructor: - return true; - - case EntityType.Ambiguous: - // let overload resolution deal with it - return true; - } - ITypedEntity typed = entity as ITypedEntity; - return null == typed ? false : TypeSystemServices.IsCallable(typed.Type); - } - - void PostProcessReferenceExpression(ReferenceExpression node) - { - IEntity tag = GetEntity(node); - switch (tag.EntityType) - { - case EntityType.Type: - { - if (IsStandaloneReference(node)) - { - BindExpressionType(node, TypeSystemServices.TypeType); - } - else - { - BindExpressionType(node, (IType)tag); - } - break; - } - - case EntityType.Ambiguous: - { - tag = ResolveAmbiguousReference(node, (Ambiguous)tag); - IMember resolvedMember = tag as IMember; - if (null != resolvedMember) - { - ResolveMemberInfo(node, resolvedMember); - break; - } - if (!AstUtil.IsTargetOfMethodInvocation(node) - && !AstUtil.IsTargetOfSlicing(node) - && !AstUtil.IsLhsOfAssignment(node)) - { - Error(node, CompilerErrorFactory.AmbiguousReference( - node, - node.Name, - ((Ambiguous)tag).Entities)); - } - break; - } - - case EntityType.Namespace: - { - if (IsStandaloneReference(node)) - { - Error(node, CompilerErrorFactory.NamespaceIsNotAnExpression(node, tag.Name)); - } - break; - } - - case EntityType.Parameter: - case EntityType.Local: - { - ILocalEntity local = (ILocalEntity)node.Entity; - local.IsUsed = true; - BindExpressionType(node, local.Type); - break; - } - - default: - { - if (EntityType.BuiltinFunction == tag.EntityType) - { - CheckBuiltinUsage(node, tag); - } - else - { - if (node.ExpressionType == null) - { - BindExpressionType(node, ((ITypedEntity)tag).Type); - } - } - break; - } - } - } - - protected virtual void CheckBuiltinUsage(ReferenceExpression node, IEntity entity) - { - if (!AstUtil.IsTargetOfMethodInvocation(node)) - { - Error(node, CompilerErrorFactory.BuiltinCannotBeUsedAsExpression(node, entity.Name)); - } - } - - override public bool EnterMemberReferenceExpression(MemberReferenceExpression node) - { - return null == node.ExpressionType; - } - - INamespace GetReferenceNamespace(MemberReferenceExpression expression) - { - Expression target = expression.Target; - INamespace ns = target.ExpressionType; - if (null != ns) - { - return GetConcreteExpressionType(target); - } - return (INamespace)GetEntity(target); - } - - protected virtual void LeaveExplodeExpression(UnaryExpression node) - { - IType type = GetConcreteExpressionType(node.Operand); - if (!type.IsArray) - { - Error(CompilerErrorFactory.ExplodedExpressionMustBeArray(node)); - } - BindExpressionType(node, type); - } - - override public void LeaveMemberReferenceExpression(MemberReferenceExpression node) - { - _context.TraceVerbose("LeaveMemberReferenceExpression: {0}", node); - - if (TypeSystemServices.IsError(node.Target)) - { - Error(node); - } - else - { - ProcessMemberReferenceExpression(node); - } - } - - virtual protected void MemberNotFound(MemberReferenceExpression node, INamespace ns) - { - Error(node, CompilerErrorFactory.MemberNotFound(node, ((IEntity)ns).ToString())); - } - - virtual protected bool ShouldRebindMember(IEntity entity) - { - return entity == null; - } - - IEntity ResolveMember(MemberReferenceExpression node) - { - IEntity member = node.Entity; - if (!ShouldRebindMember(member)) return member; - - INamespace ns = GetReferenceNamespace(node); - member = NameResolutionService.Resolve(ns, node.Name); - if (null != member) return member; - - member = NameResolutionService.ResolveExtension(ns, node.Name); - if (null == member) MemberNotFound(node, ns); - - return member; - } - - virtual protected void ProcessMemberReferenceExpression(MemberReferenceExpression node) - { - IEntity member = ResolveMember(node); - if (null == member) return; - - if (EntityType.Ambiguous == member.EntityType) - { - member = ResolveAmbiguousReference(node, (Ambiguous)member); - } - - EnsureRelatedNodeWasVisited(node, member); - - IMember memberInfo = member as IMember; - if (null != memberInfo) - { - // methods will be checked later - if (EntityType.Method != memberInfo.EntityType) - { - if (!AssertTargetContext(node, memberInfo)) - { - Error(node); - return; - } - - BindExpressionType(node, GetInferredType(memberInfo)); - } - else - { - BindExpressionType(node, memberInfo.Type); - } - } - - if (EntityType.Property == member.EntityType) - { - IProperty property = (IProperty)member; - if (IsIndexedProperty(property)) - { - if (!AstUtil.IsTargetOfSlicing(node) - && (!property.IsExtension || property.GetParameters().Length > 1)) - { - Error(node, CompilerErrorFactory.PropertyRequiresParameters( - AstUtil.GetMemberAnchor(node), - member.FullName)); - return; - } - } - if (IsWriteOnlyProperty(property) && !IsBeingAssignedTo(node)) - { - Error(node, CompilerErrorFactory.PropertyIsWriteOnly( - AstUtil.GetMemberAnchor(node), - member.FullName)); - } - } - else if (EntityType.Event == member.EntityType) - { - if (!AstUtil.IsTargetOfMethodInvocation(node) && - !AstUtil.IsLhsOfInPlaceAddSubtract(node)) - { - if (CurrentType == memberInfo.DeclaringType) - { - InternalEvent ev = (InternalEvent)member; - node.Name = ev.BackingField.Name; - node.Entity = ev.BackingField; - BindExpressionType(node, ev.BackingField.Type); - return; - } - else - { - Error(node, - CompilerErrorFactory.EventIsNotAnExpression(node, - member.FullName)); - } - } - } - - Bind(node, member); - PostProcessReferenceExpression(node); - } - - private bool IsBeingAssignedTo(MemberReferenceExpression node) - { - Node current = node; - Node parent = current.ParentNode; - while (!(parent is BinaryExpression)) - { - current = parent; - parent = parent.ParentNode; - if (parent == null || !(parent is Expression)) return false; - } - return ((BinaryExpression)parent).Left == current; - } - - private bool IsWriteOnlyProperty(IProperty property) - { - return null == property.GetGetMethod(); - } - - private IEntity ResolveAmbiguousLValue(Expression sourceNode, Ambiguous candidates, Expression rvalue) - { - if (!candidates.AllEntitiesAre(EntityType.Property)) return null; - - IEntity[] entities = candidates.Entities; - IEntity[] getters = GetSetMethods(entities); - ExpressionCollection args = new ExpressionCollection(); - args.Add(rvalue); - IEntity found = GetCorrectCallableReference(sourceNode, args, getters); - if (null != found && EntityType.Method == found.EntityType) - { - IProperty property = (IProperty)entities[GetIndex(getters, found)]; - BindProperty(sourceNode, property); - return property; - } - return null; - } - - private static void BindProperty(Expression expression, IProperty property) - { - expression.Entity = property; - expression.ExpressionType = property.Type; - } - - private IEntity ResolveAmbiguousReference(ReferenceExpression node, Ambiguous candidates) - { - if (!AstUtil.IsTargetOfSlicing(node) - && !AstUtil.IsLhsOfAssignment(node)) - { - if (candidates.AllEntitiesAre(EntityType.Property)) - { - return ResolveAmbiguousPropertyReference(node, candidates, EmptyExpressionCollection); - } - else if (candidates.AllEntitiesAre(EntityType.Method)) - { - return ResolveAmbiguousMethodReference(node, candidates, EmptyExpressionCollection); - } - } - return candidates; - } - - private IEntity ResolveAmbiguousMethodReference(ReferenceExpression node, Ambiguous candidates, ExpressionCollection args) - { - //BOO-656 - if (!AstUtil.IsTargetOfMethodInvocation(node) - && !AstUtil.IsTargetOfSlicing(node) - && !AstUtil.IsLhsOfAssignment(node)) - { - return candidates.Entities[0]; - } - return candidates; - } - - private IEntity ResolveAmbiguousPropertyReference(ReferenceExpression node, Ambiguous candidates, ExpressionCollection args) - { - IEntity[] entities = candidates.Entities; - IEntity[] getters = GetGetMethods(entities); - IEntity found = GetCorrectCallableReference(node, args, getters); - if (null != found && EntityType.Method == found.EntityType) - { - IProperty property = (IProperty)entities[GetIndex(getters, found)]; - BindProperty(node, property); - return property; - } - return candidates; - } - - private int GetIndex(IEntity[] entities, IEntity entity) - { - for (int i=0; i - /// Process a iterator and its declarations and returns a new iterator - /// expression if necessary. - /// - protected Expression ProcessIterator(Expression iterator, DeclarationCollection declarations) - { - iterator = GetCorrectIterator(iterator); - ProcessDeclarationsForIterator(declarations, GetExpressionType(iterator)); - return iterator; - } - - public override void OnGotoStatement(GotoStatement node) - { - // don't try to resolve label references - } - - override public void OnForStatement(ForStatement node) - { - Visit(node.Iterator); - node.Iterator = ProcessIterator(node.Iterator, node.Declarations); - VisitForStatementBlock(node); - } - - protected void VisitForStatementBlock(ForStatement node) - { - EnterForNamespace(node); - Visit(node.Block); - LeaveNamespace(); - } - - private void EnterForNamespace(ForStatement node) - { - EnterNamespace(new DeclarationsNamespace(CurrentNamespace, TypeSystemServices, node.Declarations)); - } - - override public void OnUnpackStatement(UnpackStatement node) - { - Visit(node.Expression); - - node.Expression = GetCorrectIterator(node.Expression); - - IType defaultDeclarationType = GetEnumeratorItemType(GetExpressionType(node.Expression)); - foreach (Declaration d in node.Declarations) - { - bool declareNewVariable = d.Type != null; - - ProcessDeclarationType(defaultDeclarationType, d); - if (declareNewVariable) - { - AssertUniqueLocal(d); - } - else - { - IEntity tag = NameResolutionService.Resolve(d.Name); - if (null != tag) - { - Bind(d, tag); - AssertLValue(d); - continue; - } - } - DeclareLocal(d, false); - } - } - - override public void LeaveRaiseStatement(RaiseStatement node) - { - if (node.Exception == null) return; - - IType exceptionType = GetExpressionType(node.Exception); - if (TypeSystemServices.StringType == exceptionType) - { - node.Exception = CodeBuilder.CreateConstructorInvocation( - node.Exception.LexicalInfo, - ApplicationException_StringConstructor, - node.Exception); - } - else if (!TypeSystemServices.ExceptionType.IsAssignableFrom(exceptionType)) - { - Error(CompilerErrorFactory.InvalidRaiseArgument(node.Exception, - exceptionType.ToString())); - } - } - - override public void OnExceptionHandler(ExceptionHandler node) - { - if (null == node.Declaration) - { - node.Declaration = new Declaration(node.LexicalInfo, - "___exception", - CodeBuilder.CreateTypeReference(TypeSystemServices.ExceptionType)); - } - else - { - if (null == node.Declaration.Type) - { - node.Declaration.Type = CodeBuilder.CreateTypeReference(TypeSystemServices.ExceptionType); - } - else - { - Visit(node.Declaration.Type); - } - } - - node.Declaration.Entity = DeclareLocal(node.Declaration, node.Declaration.Name, GetType(node.Declaration.Type), true); - EnterNamespace(new DeclarationsNamespace(CurrentNamespace, TypeSystemServices, node.Declaration)); - try - { - Visit(node.Block); - } - finally - { - LeaveNamespace(); - } - } - - protected virtual bool IsValidIncrementDecrementOperand(Expression e) - { - IType type = GetExpressionType(e); - return IsNumber(type) || TypeSystemServices.IsDuckType(type); - } - - void LeaveIncrementDecrement(UnaryExpression node) - { - if (AssertLValue(node.Operand)) - { - if (!IsValidIncrementDecrementOperand(node.Operand)) - { - InvalidOperatorForType(node); - } - else - { - ExpandIncrementDecrement(node); - } - } - else - { - Error(node); - } - } - - void ExpandIncrementDecrement(UnaryExpression node) - { - Node expansion = null; - if (IsArraySlicing(node.Operand)) - { - expansion = ExpandIncrementDecrementArraySlicing(node); - } - else - { - expansion = ExpandSimpleIncrementDecrement(node); - } - node.ParentNode.Replace(node, expansion); - Visit(expansion); - } - - Expression ExpandIncrementDecrementArraySlicing(UnaryExpression node) - { - SlicingExpression slicing = (SlicingExpression)node.Operand; - CheckNoComplexSlicing(slicing); - Visit(slicing); - return CreateSideEffectAwareSlicingOperation( - node.LexicalInfo, - GetEquivalentBinaryOperator(node.Operator), - slicing, - CodeBuilder.CreateIntegerLiteral(1), - DeclareOldValueTempIfNeeded(node)); - } - - private Expression CreateSideEffectAwareSlicingOperation(LexicalInfo lexicalInfo, BinaryOperatorType binaryOperator, SlicingExpression lvalue, Expression rvalue, InternalLocal returnValue) - { - MethodInvocationExpression eval = CodeBuilder.CreateEvalInvocation(lexicalInfo); - if (HasSideEffect(lvalue.Target)) - { - InternalLocal temp = AddInitializedTempLocal(eval, lvalue.Target); - lvalue.Target = CodeBuilder.CreateReference(temp); - } - - foreach (Slice slice in lvalue.Indices) - { - Expression index = slice.Begin; - if (HasSideEffect(index)) - { - InternalLocal temp = AddInitializedTempLocal(eval, index); - slice.Begin = CodeBuilder.CreateReference(temp); - } - } - - BinaryExpression addition = CodeBuilder.CreateBoundBinaryExpression( - GetExpressionType(lvalue), - binaryOperator, - CloneOrAssignToTemp(returnValue, lvalue), - rvalue); - Expression expansion = CodeBuilder.CreateAssignment( - lvalue.CloneNode(), - addition); - // Resolve operator overloads if any - BindArithmeticOperator(addition); - if (eval.Arguments.Count > 0 || null != returnValue) - { - eval.Arguments.Add(expansion); - if (null != returnValue) - { - eval.Arguments.Add(CodeBuilder.CreateReference(returnValue)); - } - BindExpressionType(eval, GetExpressionType(lvalue)); - expansion = eval; - } - return expansion; - } - - InternalLocal AddInitializedTempLocal(MethodInvocationExpression eval, Expression initializer) - { - InternalLocal temp = DeclareTempLocal(GetExpressionType(initializer)); - eval.Arguments.Add( - CodeBuilder.CreateAssignment( - CodeBuilder.CreateReference(temp), - initializer)); - return temp; - } - - InternalLocal DeclareOldValueTempIfNeeded(UnaryExpression node) - { - return AstUtil.IsPostUnaryOperator(node.Operator) - ? DeclareTempLocal(GetExpressionType(node.Operand)) - : null; - } - - Expression ExpandSimpleIncrementDecrement(UnaryExpression node) - { - InternalLocal oldValue = DeclareOldValueTempIfNeeded(node); - - BinaryExpression addition = CodeBuilder.CreateBoundBinaryExpression( - GetExpressionType(node.Operand), - GetEquivalentBinaryOperator(node.Operator), - CloneOrAssignToTemp(oldValue, node.Operand), - CodeBuilder.CreateIntegerLiteral(1)); - - BinaryExpression assign = CodeBuilder.CreateAssignment( - node.LexicalInfo, - node.Operand, - addition); - - // Resolve operator overloads if any - BindArithmeticOperator(addition); - - return null == oldValue - ? (Expression) assign - : CodeBuilder.CreateEvalInvocation( - node.LexicalInfo, - assign, - CodeBuilder.CreateReference(oldValue)); - } - - Expression CloneOrAssignToTemp(InternalLocal temp, Expression operand) - { - return null == temp - ? operand.CloneNode() - : CodeBuilder.CreateAssignment( - CodeBuilder.CreateReference(temp), - operand.CloneNode()); - } - - BinaryOperatorType GetEquivalentBinaryOperator(UnaryOperatorType op) - { - return op == UnaryOperatorType.Increment || op == UnaryOperatorType.PostIncrement - ? BinaryOperatorType.Addition - : BinaryOperatorType.Subtraction; - } - - UnaryOperatorType GetRelatedPreOperator(UnaryOperatorType op) - { - switch (op) - { - case UnaryOperatorType.PostIncrement: - { - return UnaryOperatorType.Increment; - } - case UnaryOperatorType.PostDecrement: - { - return UnaryOperatorType.Decrement; - } - } - throw new ArgumentException("op"); - } - - override public bool EnterUnaryExpression(UnaryExpression node) - { - if (AstUtil.IsPostUnaryOperator(node.Operator)) - { - if (NodeType.ExpressionStatement == node.ParentNode.NodeType) - { - // nothing to do, a post operator inside a statement - // behaves just like its equivalent pre operator - node.Operator = GetRelatedPreOperator(node.Operator); - } - } - return true; - } - - override public void LeaveUnaryExpression(UnaryExpression node) - { - switch (node.Operator) - { - case UnaryOperatorType.Explode: - { - LeaveExplodeExpression(node); - break; - } - case UnaryOperatorType.LogicalNot: - { - LeaveLogicalNot(node); - break; - } - - case UnaryOperatorType.Increment: - case UnaryOperatorType.PostIncrement: - case UnaryOperatorType.Decrement: - case UnaryOperatorType.PostDecrement: - { - LeaveIncrementDecrement(node); - break; - } - - case UnaryOperatorType.UnaryNegation: - { - LeaveUnaryNegation(node); - break; - } - - case UnaryOperatorType.OnesComplement: - { - LeaveOnesComplement(node); - break; - } - - default: - { - NotImplemented(node, "unary operator not supported"); - break; - } - } - } - - private void LeaveOnesComplement(UnaryExpression node) - { - if (IsPrimitiveOnesComplementOperand(node.Operand)) - { - BindExpressionType(node, GetExpressionType(node.Operand)); - } - else - { - ProcessOperatorOverload(node); - } - } - - private bool IsPrimitiveOnesComplementOperand(Expression operand) - { - IType type = GetExpressionType(operand); - return TypeSystemServices.IsIntegerNumber(type); - } - - private void LeaveLogicalNot(UnaryExpression node) - { - node.Operand = AssertBoolContext(node.Operand); - BindExpressionType(node, TypeSystemServices.BoolType); - } - - private void LeaveUnaryNegation(UnaryExpression node) - { - if (IsPrimitiveNumber(node.Operand)) - { - BindExpressionType(node, GetExpressionType(node.Operand)); - } - else - { - ProcessOperatorOverload(node); - } - } - - private void ProcessOperatorOverload(UnaryExpression node) - { - if (! ResolveOperator(node)) - { - InvalidOperatorForType(node); - } - } - - override public bool EnterBinaryExpression(BinaryExpression node) - { - if (BinaryOperatorType.Assign == node.Operator) - { - if (NodeType.ReferenceExpression == node.Left.NodeType && - null == node.Left.Entity) - { - // Auto local declaration: - // assign to unknown reference implies local - // declaration - ReferenceExpression reference = (ReferenceExpression)node.Left; - IEntity info = NameResolutionService.Resolve(reference.Name); - if (null == info || TypeSystemServices.IsBuiltin(info) || IsInaccessible(info)) - { - Visit(node.Right); - IType expressionType = MapNullToObject(GetConcreteExpressionType(node.Right)); - IEntity local = DeclareLocal(reference, reference.Name, expressionType); - reference.Entity = local; - BindExpressionType(node.Left, expressionType); - BindExpressionType(node, expressionType); - return false; - } - } - } - return true; - } - - bool IsInaccessible(IEntity info) - { - IAccessibleMember accessible = info as IAccessibleMember; - if (accessible != null && accessible.IsPrivate - && accessible.DeclaringType != CurrentType) - { - return true; - } - return false; - } - - override public void LeaveBinaryExpression(BinaryExpression node) - { - if (TypeSystemServices.IsUnknown(node.Left) || - TypeSystemServices.IsUnknown(node.Right)) - { - BindExpressionType(node, Unknown.Default); - return; - } - - if (TypeSystemServices.IsError(node.Left) - || TypeSystemServices.IsError(node.Right)) - { - Error(node); - return; - } - BindBinaryExpression(node); - } - - protected virtual void BindBinaryExpression(BinaryExpression node) - { - switch (node.Operator) - { - case BinaryOperatorType.Assign: - { - BindAssignment(node); - break; - } - - case BinaryOperatorType.Addition: - { - if (GetExpressionType(node.Left).IsArray && - GetExpressionType(node.Right).IsArray) - { - BindArrayAddition(node); - } - else - { - BindArithmeticOperator(node); - } - break; - } - - case BinaryOperatorType.Subtraction: - case BinaryOperatorType.Multiply: - case BinaryOperatorType.Division: - case BinaryOperatorType.Modulus: - case BinaryOperatorType.Exponentiation: - { - BindArithmeticOperator(node); - break; - } - - case BinaryOperatorType.TypeTest: - { - BindTypeTest(node); - break; - } - - case BinaryOperatorType.ReferenceEquality: - { - BindReferenceEquality(node); - break; - } - - case BinaryOperatorType.ReferenceInequality: - { - BindReferenceEquality(node); - break; - } - - case BinaryOperatorType.Or: - case BinaryOperatorType.And: - { - BindLogicalOperator(node); - break; - } - - case BinaryOperatorType.BitwiseAnd: - case BinaryOperatorType.BitwiseOr: - case BinaryOperatorType.ExclusiveOr: - case BinaryOperatorType.ShiftLeft: - case BinaryOperatorType.ShiftRight: - { - BindBitwiseOperator(node); - break; - } - - case BinaryOperatorType.InPlaceSubtraction: - case BinaryOperatorType.InPlaceAddition: - { - BindInPlaceAddSubtract(node); - break; - } - - case BinaryOperatorType.InPlaceShiftLeft: - case BinaryOperatorType.InPlaceShiftRight: - case BinaryOperatorType.InPlaceDivision: - case BinaryOperatorType.InPlaceMultiply: - case BinaryOperatorType.InPlaceBitwiseOr: - case BinaryOperatorType.InPlaceBitwiseAnd: - { - BindInPlaceArithmeticOperator(node); - break; - } - - case BinaryOperatorType.GreaterThan: - case BinaryOperatorType.GreaterThanOrEqual: - case BinaryOperatorType.LessThan: - case BinaryOperatorType.LessThanOrEqual: - case BinaryOperatorType.Inequality: - case BinaryOperatorType.Equality: - { - BindCmpOperator(node); - break; - } - - default: - { - if (!ResolveOperator(node)) - { - InvalidOperatorForTypes(node); - } - break; - } - } - } - - IType GetMostGenericType(BinaryExpression node) - { - return GetMostGenericType( - GetExpressionType(node.Left), - GetExpressionType(node.Right)); - } - - void BindBitwiseOperator(BinaryExpression node) - { - IType lhs = GetExpressionType(node.Left); - IType rhs = GetExpressionType(node.Right); - - if (TypeSystemServices.IsIntegerOrBool(lhs) && - TypeSystemServices.IsIntegerOrBool(rhs)) - { - BindExpressionType(node, TypeSystemServices.GetPromotedNumberType(lhs, rhs)); - } - else - { - if (lhs.IsEnum && rhs == lhs) - { - BindExpressionType(node, lhs); - } - else - { - if (!ResolveOperator(node)) - { - InvalidOperatorForTypes(node); - } - } - } - } - - bool IsChar(IType type) - { - return TypeSystemServices.CharType == type; - } - - void BindCmpOperator(BinaryExpression node) - { - IType lhs = GetExpressionType(node.Left); - IType rhs = GetExpressionType(node.Right); - - if (IsPrimitiveNumber(lhs) && IsPrimitiveNumber(rhs)) - { - BindExpressionType(node, TypeSystemServices.BoolType); - } - else if (lhs.IsEnum || rhs.IsEnum || IsChar(lhs) || IsChar(rhs)) - { - if (lhs == rhs || IsPrimitiveNumber(rhs) || IsPrimitiveNumber(lhs)) - { - BindExpressionType(node, TypeSystemServices.BoolType); - } - else - { - if (!ResolveOperator(node)) - { - InvalidOperatorForTypes(node); - } - } - } - else if (!ResolveOperator(node)) - { - switch (node.Operator) - { - case BinaryOperatorType.Equality: - { - if (OptimizeNullComparisons && (IsNull(node.Left) || IsNull(node.Right))) - { - node.Operator = BinaryOperatorType.ReferenceEquality; - BindReferenceEquality(node); - break; - } - Expression expression = CreateEquals(node); - node.ParentNode.Replace(node, expression); - break; - } - - case BinaryOperatorType.Inequality: - { - if (OptimizeNullComparisons && (IsNull(node.Left) || IsNull(node.Right))) - { - node.Operator = BinaryOperatorType.ReferenceInequality; - BindReferenceEquality(node); - break; - } - Expression expression = CreateEquals(node); - Node parent = node.ParentNode; - parent.Replace(node, CodeBuilder.CreateNotExpression(expression)); - break; - } - - default: - { - InvalidOperatorForTypes(node); - break; - } - } - } - } - - static bool IsNull(Expression node) - { - return NodeType.NullLiteralExpression == node.NodeType; - } - - void BindLogicalOperator(BinaryExpression node) - { - node.Left = AssertBoolContext(node.Left); - node.Right = AssertBoolContext(node.Right); - BindExpressionType(node, GetMostGenericType(node)); - } - - void BindInPlaceAddSubtract(BinaryExpression node) - { - IEntity entity = node.Left.Entity; - if (null != entity && - (EntityType.Event == entity.EntityType - || EntityType.Ambiguous == entity.EntityType)) - { - BindEventSubscription(node); - } - else - { - BindInPlaceArithmeticOperator(node); - } - } - - void BindEventSubscription(BinaryExpression node) - { - IEntity tag = GetEntity(node.Left); - if (EntityType.Event != tag.EntityType) - { - if (EntityType.Ambiguous == tag.EntityType) - { - IList found = ((Ambiguous)tag).Filter(IsPublicEventFilter); - if (found.Count != 1) - { - tag = null; - } - else - { - tag = (IEntity)found[0]; - Bind(node.Left, tag); - } - } - } - - IEvent eventInfo = (IEvent)tag; - IType rtype = GetExpressionType(node.Right); - if (!AssertDelegateArgument(node, eventInfo, rtype)) - { - Error(node); - return; - } - - IMethod method = null; - if (node.Operator == BinaryOperatorType.InPlaceAddition) - { - method = eventInfo.GetAddMethod(); - } - else - { - method = eventInfo.GetRemoveMethod(); - CallableSignature expected = GetCallableSignature(eventInfo.Type); - CallableSignature actual = GetCallableSignature(node.Right); - if (expected != actual) - { - Warnings.Add( - CompilerWarningFactory.InvalidEventUnsubscribe( - node, - eventInfo.FullName, - expected)); - } - } - - MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation( - ((MemberReferenceExpression)node.Left).Target, - method, - node.Right); - node.ParentNode.Replace(node, mie); - } - - CallableSignature GetCallableSignature(Expression node) - { - return GetCallableSignature(GetExpressionType(node)); - } - - CallableSignature GetCallableSignature(IType type) - { - return ((ICallableType)type).GetSignature(); - } - - virtual protected void ProcessBuiltinInvocation(BuiltinFunction function, MethodInvocationExpression node) - { - switch (function.FunctionType) - { - case BuiltinFunctionType.Len: - { - ProcessLenInvocation(node); - break; - } - - case BuiltinFunctionType.AddressOf: - { - ProcessAddressOfInvocation(node); - break; - } - - case BuiltinFunctionType.Eval: - { - ProcessEvalInvocation(node); - break; - } - - default: - { - NotImplemented(node, "BuiltinFunction: " + function.FunctionType); - break; - } - } - } - - void ProcessSwitchInvocation(MethodInvocationExpression node) - { - BindSwitchLabelReferences(node); - if (CheckSwitchArguments(node)) return; - Error(node, CompilerErrorFactory.InvalidSwitch(node.Target)); - } - - private static void BindSwitchLabelReferences(MethodInvocationExpression node) - { - for (int i = 1; i < node.Arguments.Count; ++i) - { - ReferenceExpression label = (ReferenceExpression)node.Arguments[i]; - label.ExpressionType = Unknown.Default; - } - } - - bool CheckSwitchArguments(MethodInvocationExpression node) - { - ExpressionCollection args = node.Arguments; - if (args.Count > 1) - { - Visit(args[0]); - if (TypeSystemServices.IsIntegerNumber(GetExpressionType(args[0]))) - { - for (int i=1; i 0) - { - int allButLast = node.Arguments.Count-1; - for (int i=0; i 2)) - { - Error(node, CompilerErrorFactory.MethodArgumentCount(node.Target, "len", node.Arguments.Count)); - return; - } - - MethodInvocationExpression resultingNode = null; - - Expression target = node.Arguments[0]; - IType type = GetExpressionType(target); - bool isArray = TypeSystemServices.ArrayType.IsAssignableFrom(type); - - if ((!isArray) && (node.Arguments.Count != 1)) - { - Error(node, CompilerErrorFactory.MethodArgumentCount(node.Target, "len", node.Arguments.Count)); - } - if (TypeSystemServices.IsSystemObject(type)) - { - resultingNode = CodeBuilder.CreateMethodInvocation(RuntimeServices_Len, target); - } - else if (TypeSystemServices.StringType == type) - { - resultingNode = CodeBuilder.CreateMethodInvocation(target, String_get_Length); - } - else if (isArray) - { - if (node.Arguments.Count == 1) - { - resultingNode = CodeBuilder.CreateMethodInvocation(target, Array_get_Length); - } - else - { - resultingNode = CodeBuilder.CreateMethodInvocation(target, - Array_GetLength, node.Arguments[1]); - } - } - else if (TypeSystemServices.ICollectionType.IsAssignableFrom(type)) - { - resultingNode = CodeBuilder.CreateMethodInvocation(target, ICollection_get_Count); - } - else - { - Error(CompilerErrorFactory.InvalidLen(target, type.ToString())); - } - if (null != resultingNode) - { - node.ParentNode.Replace(node, resultingNode); - } - } - - void CheckListLiteralArgumentInArrayConstructor(IType expectedElementType, MethodInvocationExpression constructor) - { - ListLiteralExpression elements = constructor.Arguments[1] as ListLiteralExpression; - if (null == elements) return; - CheckItems(expectedElementType, elements.Items); - } - - private void CheckItems(IType expectedElementType, ExpressionCollection items) - { - foreach (Expression element in items) - { - AssertTypeCompatibility(element, expectedElementType, GetExpressionType(element)); - } - } - - void ApplyBuiltinMethodTypeInference(MethodInvocationExpression expression, IMethod method) - { - IType inferredType = null; - - if (Array_TypedEnumerableConstructor == method || - Array_TypedCollectionConstructor == method || - Array_TypedConstructor2 == method) - { - IType type = TypeSystemServices.GetReferencedType(expression.Arguments[0]); - if (null != type) - { - if (Array_TypedCollectionConstructor == method) - { - CheckListLiteralArgumentInArrayConstructor(type, expression); - } - inferredType = TypeSystemServices.GetArrayType(type, 1); - } - } - else if (MultiDimensionalArray_TypedConstructor == method) - { - IType type = TypeSystemServices.GetReferencedType(expression.Arguments[0]); - if (null != type) - { - inferredType = TypeSystemServices.GetArrayType(type, expression.Arguments.Count-1); - } - } - else if (Array_EnumerableConstructor == method) - { - IType enumeratorItemType = GetEnumeratorItemType(GetExpressionType(expression.Arguments[0])); - if (TypeSystemServices.ObjectType != enumeratorItemType) - { - inferredType = TypeSystemServices.GetArrayType(enumeratorItemType, 1); - expression.Target.Entity = Array_TypedEnumerableConstructor; - expression.ExpressionType = Array_TypedEnumerableConstructor.ReturnType; - expression.Arguments.Insert(0, CodeBuilder.CreateReference(enumeratorItemType)); - } - } - - if (null != inferredType) - { - Node parent = expression.ParentNode; - parent.Replace(expression, - CodeBuilder.CreateCast(inferredType, expression)); - } - } - - protected virtual IEntity ResolveAmbiguousMethodInvocation(MethodInvocationExpression node, Ambiguous entity) - { - _context.TraceVerbose("{0}: resolving ambigous method invocation: {1}", node.LexicalInfo, entity); - - IEntity resolved = ResolveCallableReference(node, entity); - if (null != resolved) return resolved; - - if (TryToProcessAsExtensionInvocation(node)) return null; - - return CantResolveAmbiguousMethodInvocation(node, entity.Entities); - } - - private IEntity ResolveCallableReference(MethodInvocationExpression node, Ambiguous entity) - { - IEntity resolved = _callableResolution.ResolveCallableReference(node.Arguments, entity.Entities); - if (null == resolved) return null; - - IMember member = (IMember)resolved; - if (NodeType.ReferenceExpression == node.Target.NodeType) - { - ResolveMemberInfo((ReferenceExpression)node.Target, member); - } - else - { - Bind(node.Target, member); - BindExpressionType(node.Target, member.Type); - } - return resolved; - } - - private bool TryToProcessAsExtensionInvocation(MethodInvocationExpression node) - { - IEntity extension = ResolveExtension(node); - if (null == extension) return false; - - ProcessExtensionMethodInvocation(node, extension); - return true; - } - - private IEntity ResolveExtension(MethodInvocationExpression node) - { - MemberReferenceExpression mre = node.Target as MemberReferenceExpression; - if (mre == null) return null; - - return NameResolutionService.ResolveExtension(GetReferenceNamespace(mre), mre.Name); - } - - protected virtual IEntity CantResolveAmbiguousMethodInvocation(MethodInvocationExpression node, IEntity[] entities) - { - EmitCallableResolutionError(node, entities, node.Arguments); - Error(node); - return null; - } - - override public void OnMethodInvocationExpression(MethodInvocationExpression node) - { - if (null != node.ExpressionType) - { - _context.TraceVerbose("{0}: Method invocation already bound.", node.LexicalInfo); - return; - } - - Visit(node.Target); - - IEntity targetEntity = node.Target.Entity; - if (BuiltinFunction.Switch == targetEntity) - { - ProcessSwitchInvocation(node); - return; - } - - Visit(node.Arguments); - - if (TypeSystemServices.IsError(node.Target) - || TypeSystemServices.IsErrorAny(node.Arguments)) - { - Error(node); - return; - } - - if (null == targetEntity) - { - ProcessGenericMethodInvocation(node); - return; - } - - if (IsOrContainsExtensionMethod(targetEntity)) - { - ProcessExtensionMethodInvocation(node, targetEntity); - return; - } - - ProcessMethodInvocationExpression(node, targetEntity); - } - - private void ProcessMethodInvocationExpression(MethodInvocationExpression node, IEntity targetEntity) - { - switch (targetEntity.EntityType) - { - case EntityType.Ambiguous: - { - ProcessAmbiguousMethodInvocation(node, targetEntity); - break; - } - case EntityType.BuiltinFunction: - { - ProcessBuiltinInvocation((BuiltinFunction)targetEntity, node); - break; - } - case EntityType.Event: - { - ProcessEventInvocation((IEvent)targetEntity, node); - break; - } - - case EntityType.Method: - { - ProcessMethodInvocation(node, targetEntity); - break; - } - - case EntityType.Constructor: - { - ProcessConstructorInvocation(node, targetEntity); - break; - } - - case EntityType.Type: - { - ProcessTypeInvocation(node); - break; - } - - case EntityType.Error: - { - Error(node); - break; - } - - default: - { - ProcessGenericMethodInvocation(node); - break; - } - } - } - - protected virtual void ProcessAmbiguousMethodInvocation(MethodInvocationExpression node, IEntity targetEntity) - { - targetEntity = ResolveAmbiguousMethodInvocation(node, (Ambiguous)targetEntity); - if (null == targetEntity) return; - ProcessMethodInvocationExpression(node, targetEntity); - } - - private void ProcessConstructorInvocation(MethodInvocationExpression node, IEntity targetEntity) - { - NamedArgumentsNotAllowed(node); - InternalConstructor constructorInfo = targetEntity as InternalConstructor; - if (null != constructorInfo) - { - IType targetType = null; - if (NodeType.SuperLiteralExpression == node.Target.NodeType) - { - constructorInfo.HasSuperCall = true; - targetType = constructorInfo.DeclaringType.BaseType; - } - else if (node.Target.NodeType == NodeType.SelfLiteralExpression) - { - constructorInfo.HasSelfCall = true; - targetType = constructorInfo.DeclaringType; - } - - IConstructor targetConstructorInfo = GetCorrectConstructor(node, targetType, node.Arguments); - if (null != targetConstructorInfo) - { - Bind(node.Target, targetConstructorInfo); - } - } - } - - protected virtual void ProcessMethodInvocation(MethodInvocationExpression node, IEntity targetEntity) - { - IMethod targetMethod = (IMethod)targetEntity; - if (!CheckParameters(targetMethod.CallableType, node.Arguments, false)) - { - if (TryToProcessAsExtensionInvocation(node)) return; - AssertParameters(node, targetMethod, node.Arguments); - } - - AssertTargetContext(node.Target, targetMethod); - NamedArgumentsNotAllowed(node); - - EnsureRelatedNodeWasVisited(node.Target, targetMethod); - BindExpressionType(node, GetInferredType(targetMethod)); - ApplyBuiltinMethodTypeInference(node, targetMethod); - } - - private void NamedArgumentsNotAllowed(MethodInvocationExpression node) - { - if (node.NamedArguments.Count == 0) return; - Error(CompilerErrorFactory.NamedArgumentsNotAllowed(node.NamedArguments[0])); - } - - private void ProcessExtensionMethodInvocation(MethodInvocationExpression node, IEntity targetEntity) - { - PreNormalizeExtensionInvocation(node); - if (EntityType.Ambiguous == targetEntity.EntityType) - { - targetEntity = ResolveAmbiguousExtension(node, (Ambiguous)targetEntity); - if (null == targetEntity) return; - } - IMethod targetMethod = (IMethod)targetEntity; - PostNormalizationExtensionInvocation(node, targetMethod); - NamedArgumentsNotAllowed(node); - AssertParameters(node, targetMethod, node.Arguments); - BindExpressionType(node, targetMethod.ReturnType); - } - - private IEntity ResolveAmbiguousExtension(MethodInvocationExpression node, Ambiguous ambiguous) - { - IEntity resolved = ResolveCallableReference(node, ambiguous); - if (null != resolved) return resolved; - - return CantResolveAmbiguousMethodInvocation(node, ambiguous.Entities); - } - - private bool IsOrContainsExtensionMethod(IEntity entity) - { - if (entity.EntityType == EntityType.Ambiguous) return IsExtensionMethod(((Ambiguous)entity).Entities[0]); - return IsExtensionMethod(entity); - } - - private bool IsExtensionMethod(IEntity entity) - { - if (EntityType.Method != entity.EntityType) return false; - return ((IMethod)entity).IsExtension; - } - - private void PostNormalizationExtensionInvocation(MethodInvocationExpression node, IMethod targetMethod) - { - node.Target = CodeBuilder.CreateMethodReference(node.Target.LexicalInfo, targetMethod); - } - - private static void PreNormalizeExtensionInvocation(MethodInvocationExpression node) - { - node.Arguments.Insert(0, ((MemberReferenceExpression)node.Target).Target); - } - - private IType GetInferredType(IMethod entity) - { - return entity.IsDuckTyped - ? this.TypeSystemServices.DuckType - : entity.ReturnType; - } - - private IType GetInferredType(IMember entity) - { - Debug.Assert(EntityType.Method != entity.EntityType); - return entity.IsDuckTyped - ? this.TypeSystemServices.DuckType - : entity.Type; - } - - void ReplaceTypeInvocationByEval(IType type, MethodInvocationExpression node) - { - Node parent = node.ParentNode; - - MethodInvocationExpression eval = CodeBuilder.CreateEvalInvocation(node.LexicalInfo); - ReferenceExpression local = CreateTempLocal(node.Target.LexicalInfo, type); - - eval.Arguments.Add(CodeBuilder.CreateAssignment(local.CloneNode(), node)); - - AddResolvedNamedArgumentsToEval(eval, node.NamedArguments, local); - - node.NamedArguments.Clear(); - - eval.Arguments.Add(local); - - BindExpressionType(eval, type); - - parent.Replace(node, eval); - } - - private void AddResolvedNamedArgumentsToEval(MethodInvocationExpression eval, ExpressionPairCollection namedArguments, ReferenceExpression instance) - { - foreach (ExpressionPair pair in namedArguments) - { - if (TypeSystemServices.IsError(pair.First)) continue; - - AddResolvedNamedArgumentToEval(eval, pair, instance); - } - } - - protected virtual void AddResolvedNamedArgumentToEval(MethodInvocationExpression eval, ExpressionPair pair, ReferenceExpression instance) - { - IEntity entity = GetEntity(pair.First); - switch (entity.EntityType) - { - case EntityType.Event: - { - IEvent member = (IEvent)entity; - eval.Arguments.Add( - CodeBuilder.CreateMethodInvocation( - pair.First.LexicalInfo, - instance.CloneNode(), - member.GetAddMethod(), - pair.Second)); - break; - } - - case EntityType.Field: - { - eval.Arguments.Add( - CodeBuilder.CreateAssignment( - pair.First.LexicalInfo, - CodeBuilder.CreateMemberReference( - instance.CloneNode(), - (IMember)entity), - pair.Second)); - break; - } - - case EntityType.Property: - { - IProperty property = (IProperty)entity; - IMethod setter = property.GetSetMethod(); - if (null == setter) - { - Error(CompilerErrorFactory.PropertyIsReadOnly( - pair.First, - property.FullName)); - } - else - { - eval.Arguments.Add( - CodeBuilder.CreateAssignment( - pair.First.LexicalInfo, - CodeBuilder.CreateMemberReference( - instance.CloneNode(), - property), - pair.Second)); - } - break; - } - } - } - - void ProcessEventInvocation(IEvent ev, MethodInvocationExpression node) - { - NamedArgumentsNotAllowed(node); - - IMethod method = ev.GetRaiseMethod(); - if (AssertParameters(node, method, node.Arguments)) - { - node.Target = CodeBuilder.CreateMemberReference( - ((MemberReferenceExpression)node.Target).Target, - method); - BindExpressionType(node, method.ReturnType); - } - } - - void ProcessCallableTypeInvocation(MethodInvocationExpression node, ICallableType type) - { - NamedArgumentsNotAllowed(node); - - if (node.Arguments.Count == 1) - { - AssertTypeCompatibility(node.Arguments[0], type, GetExpressionType(node.Arguments[0])); - node.ParentNode.Replace( - node, - CodeBuilder.CreateCast( - type, - node.Arguments[0])); - } - else - { - IConstructor ctor = GetCorrectConstructor(node, type, node.Arguments); - if (null != ctor) - { - BindConstructorInvocation(node, ctor); - } - else - { - Error(node); - } - } - } - - void ProcessTypeInvocation(MethodInvocationExpression node) - { - IType type = (IType)node.Target.Entity; - - ICallableType callableType = type as ICallableType; - if (null != callableType) - { - ProcessCallableTypeInvocation(node, callableType); - return; - } - - if (!AssertCanCreateInstance(node.Target, type)) - { - Error(node); - return; - } - - ResolveNamedArguments(type, node.NamedArguments); - if (type.IsValueType && node.Arguments.Count == 0) - { - ProcessValueTypeInstantiation(type, node); - return; - } - - IConstructor ctor = GetCorrectConstructor(node, type, node.Arguments); - if (null != ctor) - { - BindConstructorInvocation(node, ctor); - - if (node.NamedArguments.Count > 0) - { - ReplaceTypeInvocationByEval(type, node); - } - } - else - { - Error(node); - } - } - - void BindConstructorInvocation(MethodInvocationExpression node, IConstructor ctor) - { - // rebind the target now we know - // it is a constructor call - Bind(node.Target, ctor); - BindExpressionType(node.Target, ctor.Type); - BindExpressionType(node, ctor.DeclaringType); - } - - private void ProcessValueTypeInstantiation(IType type, MethodInvocationExpression node) - { - // XXX: naive and unoptimized but correct approach - // simply initialize a new temporary value type - // TODO: OPTIMIZE by detecting assignments to local variables - - MethodInvocationExpression eval = CodeBuilder.CreateEvalInvocation(node.LexicalInfo); - BindExpressionType(eval, type); - - InternalLocal local = DeclareTempLocal(type); - ReferenceExpression localReference = CodeBuilder.CreateReference(local); - eval.Arguments.Add(CodeBuilder.CreateDefaultInitializer(node.LexicalInfo, local)); - AddResolvedNamedArgumentsToEval(eval, node.NamedArguments, localReference); - eval.Arguments.Add(localReference); - - node.ParentNode.Replace(node, eval); - } - - void ProcessGenericMethodInvocation(MethodInvocationExpression node) - { - IType type = GetExpressionType(node.Target); - if (TypeSystemServices.IsCallable(type)) - { - ProcessMethodInvocationOnCallableExpression(node); - } - else - { - Error(node, - CompilerErrorFactory.TypeIsNotCallable(node.Target, type.ToString())); - } - } - - void ProcessMethodInvocationOnCallableExpression(MethodInvocationExpression node) - { - IType type = node.Target.ExpressionType; - - ICallableType delegateType = type as ICallableType; - if (null != delegateType) - { - if (AssertParameters(node.Target, delegateType, delegateType, node.Arguments)) - { - IMethod invoke = ResolveMethod(delegateType, "Invoke"); - node.Target = CodeBuilder.CreateMemberReference(node.Target, invoke); - BindExpressionType(node, invoke.ReturnType); - } - else - { - Error(node); - } - } - else if (TypeSystemServices.ICallableType.IsAssignableFrom(type)) - { - node.Target = CodeBuilder.CreateMemberReference(node.Target, ICallable_Call); - ArrayLiteralExpression arg = CodeBuilder.CreateObjectArray(node.Arguments); - node.Arguments.Clear(); - node.Arguments.Add(arg); - - BindExpressionType(node, ICallable_Call.ReturnType); - } - else if (TypeSystemServices.TypeType == type) - { - ProcessSystemTypeInvocation(node); - } - else - { - ProcessInvocationOnUnknownCallableExpression(node); - } - } - - private void ProcessSystemTypeInvocation(MethodInvocationExpression node) - { - MethodInvocationExpression invocation = CodeBuilder.CreateMethodInvocation(Activator_CreateInstance, node.Target); - if (Activator_CreateInstance.AcceptVarArgs) - { - invocation.Arguments.Extend(node.Arguments); - } - else - { - invocation.Arguments.Add(CodeBuilder.CreateObjectArray(node.Arguments)); - } - node.ParentNode.Replace(node, invocation); - } - - protected virtual void ProcessInvocationOnUnknownCallableExpression(MethodInvocationExpression node) - { - NotImplemented(node, "Method invocation on type '" + node.Target.ExpressionType + "'."); - } - - bool AssertIdentifierName(Node node, string name) - { - if (TypeSystemServices.IsPrimitive(name)) - { - Error(CompilerErrorFactory.CantRedefinePrimitive(node, name)); - return false; - } - return true; - } - - bool CheckIsNotValueType(BinaryExpression node, Expression expression) - { - IType tag = GetExpressionType(expression); - if (tag.IsValueType) - { - Error(CompilerErrorFactory.OperatorCantBeUsedWithValueType( - expression, - GetBinaryOperatorText(node.Operator), - tag.ToString())); - - return false; - } - return true; - } - - void BindAssignmentToSlice(BinaryExpression node) - { - SlicingExpression slice = (SlicingExpression)node.Left; - - if (!IsAmbiguous(slice.Target.Entity) - && GetExpressionType(slice.Target).IsArray) - { - BindAssignmentToSliceArray(node); - } - else if (TypeSystemServices.IsDuckTyped(slice.Target)) - { - BindExpressionType(node, TypeSystemServices.DuckType); - } - else - { - BindAssignmentToSliceProperty(node); - } - } - - void BindAssignmentToSliceArray(BinaryExpression node) - { - SlicingExpression slice = (SlicingExpression)node.Left; - - IArrayType sliceTargetType = (IArrayType)GetExpressionType(slice.Target); - IType lhsType = GetExpressionType(node.Right); - - foreach (Slice item in slice.Indices) - { - if (!AssertTypeCompatibility(item.Begin, TypeSystemServices.IntType, GetExpressionType(item.Begin))) - { - Error(node); - return; - } - } - - if (slice.Indices.Count > 1) - { - if (AstUtil.IsComplexSlicing(slice)) - { - // FIXME: Check type compatibility - BindAssignmentToComplexSliceArray(node); - } - else - { - if (!AssertTypeCompatibility(node.Right, sliceTargetType.GetElementType(), lhsType)) - { - Error(node); - return; - } - BindAssignmentToSimpleSliceArray(node); - } - } - else - { - if (!AssertTypeCompatibility(node.Right, sliceTargetType.GetElementType(), lhsType)) - { - Error(node); - return; - } - node.ExpressionType = sliceTargetType.GetElementType(); - } - } - - void BindAssignmentToSimpleSliceArray(BinaryExpression node) - { - SlicingExpression slice = (SlicingExpression)node.Left; - MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation( - slice.Target, - TypeSystemServices.Map(typeof(Array).GetMethod("SetValue", new Type[] { typeof(object), typeof(int[]) })), - node.Right); - for (int i = 0; i < slice.Indices.Count; i++) - { - mie.Arguments.Add(slice.Indices[i].Begin); - } - BindExpressionType(mie, TypeSystemServices.VoidType); - node.ParentNode.Replace(node, mie); - } - - void BindAssignmentToComplexSliceArray(BinaryExpression node) - { - SlicingExpression slice = (SlicingExpression)node.Left; - ArrayLiteralExpression ale = new ArrayLiteralExpression(); - ArrayLiteralExpression collapse = new ArrayLiteralExpression(); - for (int i = 0; i < slice.Indices.Count; i++) - { - ale.Items.Add(slice.Indices[i].Begin); - if (null == slice.Indices[i].End || - OmittedExpression.Default == slice.Indices[i].End) - { - ale.Items.Add(new IntegerLiteralExpression(1 + (int)((IntegerLiteralExpression)slice.Indices[i].Begin).Value)); - collapse.Items.Add(new BoolLiteralExpression(true)); - } - else - { - ale.Items.Add(slice.Indices[i].End); - collapse.Items.Add(new BoolLiteralExpression(false)); - } - } - - MethodInvocationExpression mie = CodeBuilder.CreateMethodInvocation( - RuntimeServices_SetMultiDimensionalRange1, - node.Right, - slice.Target, - ale); - - mie.Arguments.Add(collapse); - - BindExpressionType(mie, TypeSystemServices.VoidType); - BindExpressionType(ale, TypeSystemServices.Map(typeof(int[]))); - BindExpressionType(collapse, TypeSystemServices.Map(typeof(bool[]))); - node.ParentNode.Replace(node, mie); - } - - void BindAssignmentToSliceProperty(BinaryExpression node) - { - SlicingExpression slice = (SlicingExpression)node.Left; - - IEntity lhs = GetEntity(node.Left); - IMethod setter = null; - - MethodInvocationExpression mie = new MethodInvocationExpression(node.Left.LexicalInfo); - foreach (Slice index in slice.Indices) - { - mie.Arguments.Add(index.Begin); - } - mie.Arguments.Add(node.Right); - - if (EntityType.Property == lhs.EntityType) - { - IMethod setMethod = ((IProperty)lhs).GetSetMethod(); - if (null == setMethod) - { - Error(node, CompilerErrorFactory.PropertyIsReadOnly(slice.Target, lhs.FullName)); - return; - } - if (AssertParameters(node.Left, setMethod, mie.Arguments)) - { - setter = setMethod; - } - } - else if (EntityType.Ambiguous == lhs.EntityType) - { - setter = (IMethod)GetCorrectCallableReference(node.Left, mie.Arguments, GetSetMethods(lhs)); - if (setter == null) - { - Error(node.Left); - return; - } - } - - if (null == setter) - { - Error(node, CompilerErrorFactory.LValueExpected(node.Left)); - } - else - { - mie.Target = CodeBuilder.CreateMemberReference( - GetIndexedPropertySlicingTarget(slice), - setter); - BindExpressionType(mie, setter.ReturnType); - node.ParentNode.Replace(node, mie); - } - } - - private IEntity[] GetSetMethods(IEntity candidates) - { - return GetSetMethods(((Ambiguous)candidates).Entities); - } - - void BindAssignment(BinaryExpression node) - { - if (NodeType.SlicingExpression == node.Left.NodeType) - { - BindAssignmentToSlice(node); - } - else - { - ProcessAssignment(node); - } - } - - virtual protected void ProcessAssignment(BinaryExpression node) - { - TryToResolveAmbiguousAssignment(node); - ValidateAssignment(node); - BindExpressionType(node, GetExpressionType(node.Right)); - } - - virtual protected void ValidateAssignment(BinaryExpression node) - { - IEntity lhs = node.Left.Entity; - IType rtype = GetExpressionType(node.Right); - if (AssertLValue(node.Left, lhs)) - { - IType lhsType = GetExpressionType(node.Left); - AssertTypeCompatibility(node.Right, lhsType, rtype); - CheckAssignmentToIndexedProperty(node.Left, lhs); - } - } - - virtual protected void TryToResolveAmbiguousAssignment(BinaryExpression node) - { - IEntity lhs = node.Left.Entity; - if (null == lhs) return; - if (EntityType.Ambiguous != lhs.EntityType) return; - - Expression lvalue = node.Left; - lhs = ResolveAmbiguousLValue(lvalue, (Ambiguous)lhs, node.Right); - if (NodeType.ReferenceExpression == lvalue.NodeType) - { - IMember member = lhs as IMember; - if (null != member) - { - ResolveMemberInfo((ReferenceExpression)lvalue, member); - } - } - } - - private void CheckAssignmentToIndexedProperty(Node node, IEntity lhs) - { - IProperty property = lhs as IProperty; - if (null != property && IsIndexedProperty(property)) - { - Error(CompilerErrorFactory.PropertyRequiresParameters(AstUtil.GetMemberAnchor(node), property.FullName)); - } - } - - bool CheckIsaArgument(Expression e) - { - if (TypeSystemServices.TypeType != GetExpressionType(e)) - { - Error(CompilerErrorFactory.IsaArgument(e)); - return false; - } - return true; - } - - void BindTypeTest(BinaryExpression node) - { - if (CheckIsNotValueType(node, node.Left) && - CheckIsaArgument(node.Right)) - { - BindExpressionType(node, TypeSystemServices.BoolType); - } - else - { - Error(node); - } - } - - void BindReferenceEquality(BinaryExpression node) - { - if (CheckIsNotValueType(node, node.Left) && - CheckIsNotValueType(node, node.Right)) - { - BindExpressionType(node, TypeSystemServices.BoolType); - } - else - { - Error(node); - } - } - - void BindInPlaceArithmeticOperator(BinaryExpression node) - { - if (IsArraySlicing(node.Left)) - { - BindInPlaceArithmeticOperatorOnArraySlicing(node); - return; - } - - Node parent = node.ParentNode; - - Expression target = node.Left; - if (null != target.Entity && EntityType.Property == target.Entity.EntityType) - { - // if target is a property force a rebinding - target.ExpressionType = null; - } - - BinaryExpression assign = ExpandInPlaceBinaryExpression(node); - parent.Replace(node, assign); - Visit(assign); - } - - protected BinaryExpression ExpandInPlaceBinaryExpression(BinaryExpression node) - { - BinaryExpression assign = new BinaryExpression(node.LexicalInfo); - assign.Operator = BinaryOperatorType.Assign; - assign.Left = node.Left.CloneNode(); - assign.Right = node; - node.Operator = GetRelatedBinaryOperatorForInPlaceOperator(node.Operator); - return assign; - } - - private void BindInPlaceArithmeticOperatorOnArraySlicing(BinaryExpression node) - { - Node parent = node.ParentNode; - Expression expansion = CreateSideEffectAwareSlicingOperation( - node.LexicalInfo, - GetRelatedBinaryOperatorForInPlaceOperator(node.Operator), - (SlicingExpression) node.Left, - node.Right, - null); - parent.Replace(node, expansion); - } - - BinaryOperatorType GetRelatedBinaryOperatorForInPlaceOperator(BinaryOperatorType op) - { - switch (op) - { - case BinaryOperatorType.InPlaceAddition: - return BinaryOperatorType.Addition; - - case BinaryOperatorType.InPlaceSubtraction: - return BinaryOperatorType.Subtraction; - - case BinaryOperatorType.InPlaceMultiply: - return BinaryOperatorType.Multiply; - - case BinaryOperatorType.InPlaceDivision: - return BinaryOperatorType.Division; - - case BinaryOperatorType.InPlaceBitwiseAnd: - return BinaryOperatorType.BitwiseAnd; - - case BinaryOperatorType.InPlaceBitwiseOr: - return BinaryOperatorType.BitwiseOr; - - case BinaryOperatorType.InPlaceShiftLeft: - return BinaryOperatorType.ShiftLeft; - - case BinaryOperatorType.InPlaceShiftRight: - return BinaryOperatorType.ShiftRight; - } - throw new ArgumentException("op"); - } - - void BindArrayAddition(BinaryExpression node) - { - IArrayType lhs = (IArrayType)GetExpressionType(node.Left); - IArrayType rhs = (IArrayType)GetExpressionType(node.Right); - - if (lhs.GetElementType() == rhs.GetElementType()) - { - node.ParentNode.Replace( - node, - CodeBuilder.CreateCast( - lhs, - CodeBuilder.CreateMethodInvocation( - RuntimeServices_AddArrays, - CodeBuilder.CreateTypeofExpression(lhs.GetElementType()), - node.Left, - node.Right))); - } - else - { - InvalidOperatorForTypes(node); - } - } - - void BindArithmeticOperator(BinaryExpression node) - { - IType left = GetExpressionType(node.Left); - IType right = GetExpressionType(node.Right); - if (IsPrimitiveNumber(left) && IsPrimitiveNumber(right)) - { - BindExpressionType(node, TypeSystemServices.GetPromotedNumberType(left, right)); - } - else if (!ResolveOperator(node)) - { - InvalidOperatorForTypes(node); - } - } - - static string GetBinaryOperatorText(BinaryOperatorType op) - { - return BooPrinterVisitor.GetBinaryOperatorText(op); - } - - static string GetUnaryOperatorText(UnaryOperatorType op) - { - return BooPrinterVisitor.GetUnaryOperatorText(op); - } - - IEntity ResolveName(Node node, string name) - { - IEntity tag = NameResolutionService.Resolve(name); - CheckNameResolution(node, name, tag); - return tag; - } - - bool CheckNameResolution(Node node, string name, IEntity tag) - { - if (null == tag) - { - Error(CompilerErrorFactory.UnknownIdentifier(node, name)); - return false; - } - return true; - } - - private bool IsPublicEvent(IEntity tag) - { - return (EntityType.Event == tag.EntityType) && ((IMember)tag).IsPublic; - } - - private bool IsPublicFieldPropertyEvent(IEntity entity) - { - return IsFieldPropertyOrEvent(entity) && ((IMember)entity).IsPublic; - } - - private static bool IsFieldPropertyOrEvent(IEntity entity) - { - return ((EntityType.Field|EntityType.Property|EntityType.Event) & entity.EntityType) > 0; - } - - private IMember ResolvePublicFieldPropertyEvent(Expression sourceNode, IType type, string name) - { - IEntity candidate = ResolveFieldPropertyEvent(type, name); - if (null == candidate) return null; - - if (IsPublicFieldPropertyEvent(candidate)) return (IMember)candidate; - - if (candidate.EntityType != EntityType.Ambiguous) return null; - - IList found = ((Ambiguous)candidate).Filter(IsPublicFieldPropertyEventFilter); - if (found.Count == 0) return null; - if (found.Count == 1) return (IMember)found[0]; - - Error(sourceNode, CompilerErrorFactory.AmbiguousReference(sourceNode, name, found)); - return null; - } - - protected IEntity ResolveFieldPropertyEvent(IType type, string name) - { - return NameResolutionService.Resolve(type, name, EntityType.Property|EntityType.Event|EntityType.Field); - } - - void ResolveNamedArguments(IType type, ExpressionPairCollection arguments) - { - foreach (ExpressionPair arg in arguments) - { - Visit(arg.Second); - - if (NodeType.ReferenceExpression != arg.First.NodeType) - { - Error(arg.First, CompilerErrorFactory.NamedParameterMustBeIdentifier(arg)); - continue; - } - - ResolveNamedArgument(type, (ReferenceExpression)arg.First, arg.Second); - } - } - - void ResolveNamedArgument(IType type, ReferenceExpression name, Expression value) - { - IMember member = ResolvePublicFieldPropertyEvent(name, type, name.Name); - if (null == member) - { - NamedArgumentNotFound(type, name); - return; - } - - Bind(name, member); - - IType memberType = member.Type; - if (member.EntityType == EntityType.Event) - { - AssertDelegateArgument(value, member, GetExpressionType(value)); - } - else - { - AssertTypeCompatibility(value, memberType, GetExpressionType(value)); - } - } - - protected virtual void NamedArgumentNotFound(IType type, ReferenceExpression name) - { - Error(name, CompilerErrorFactory.NotAPublicFieldOrProperty(name, type.ToString(), name.Name)); - } - - bool AssertTypeCompatibility(Node sourceNode, IType expectedType, IType actualType) - { - if (TypeSystemServices.IsError(expectedType) - || TypeSystemServices.IsError(actualType)) - { - return false; - } - - if (!TypeSystemServices.AreTypesRelated(expectedType, actualType)) - { - Error(CompilerErrorFactory.IncompatibleExpressionType(sourceNode, expectedType.ToString(), actualType.ToString())); - return false; - } - return true; - } - - bool AssertDelegateArgument(Node sourceNode, ITypedEntity delegateMember, ITypedEntity argumentInfo) - { - if (!delegateMember.Type.IsAssignableFrom(argumentInfo.Type)) - { - Error(CompilerErrorFactory.EventArgumentMustBeAMethod(sourceNode, delegateMember.FullName, delegateMember.Type.ToString())); - return false; - } - return true; - } - - bool CheckParameterTypesStrictly(IMethod method, ExpressionCollection args) - { - IParameter[] parameters = method.GetParameters(); - for (int i=0; i