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