/src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs
C# | 6546 lines | 5598 code | 827 blank | 121 comment | 1076 complexity | 13f44191de145d863b2d7811f93f401c MD5 | raw file
Possible License(s): GPL-2.0
- #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.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
- using System.Reflection;
- 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;
- using Module=Boo.Lang.Compiler.Ast.Module;
- namespace Boo.Lang.Compiler.Steps
- {
- /// <summary>
- /// AST semantic evaluation.
- /// </summary>
- 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 Module _currentModule;
- protected InternalMethod _currentMethod;
- IMethod Array_EnumerableConstructor;
- IMethod Array_TypedEnumerableConstructor;
- IMethod Array_TypedCollectionConstructor;
- IMethod Array_TypedConstructor2;
- IMethod MultiDimensionalArray_TypedConstructor;
- protected CallableResolutionService _callableResolution;
- protected bool _optimizeNullComparisons = true;
- public ProcessMethodBodies()
- {
- }
- override public void Run()
- {
- NameResolutionService.Reset();
- _currentModule = null;
- _currentMethod = null;
- _methodStack = new Stack();
- _memberStack = new Stack();
- _callableResolution = InitializeCallableResolutionService();
- InitializeMemberCache();
- Visit(CompileUnit);
- }
- protected CallableResolutionService InitializeCallableResolutionService()
- {
- CallableResolutionService service = CreateCallableResolutionService();
- service.Initialize(_context);
- return service;
- }
- protected virtual CallableResolutionService CreateCallableResolutionService()
- {
- return new CallableResolutionService();
- }
- 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;
- }
- _currentModule = 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;
- _Exception_StringConstructor = null;
- _TextReaderEnumerator_lines = null;
- }
- override public void OnModule(Module module)
- {
- if (WasVisited(module)) return;
- MarkVisited(module);
- _currentModule = 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);
- }
- }
- Method initializer = (Method) node["$initializer$"];
- if (null != initializer)
- {
- AddInitializerToInstanceConstructors(node, initializer);
- node.Members.Remove(initializer);
- }
- }
- 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(getter.LexicalInfo, typeInfo);
- }
- }
- else
- {
- typeInfo = TypeSystemServices.ObjectType;
- }
- node.Type = CodeBuilder.CreateTypeReference(node.LexicalInfo, 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 entity = (InternalField)GetEntity(node);
- Visit(node.Attributes);
- Visit(node.Type);
- if (null != node.Initializer)
- {
- IType type = (null != node.Type) ? GetType(node.Type) : null;
- if (null != type && TypeSystemServices.IsNullable(type))
- {
- BindNullableInitializer(node, node.Initializer, type);
- }
- if (entity.DeclaringType.IsValueType && !node.IsStatic)
- {
- Error(
- CompilerErrorFactory.ValueTypeFieldsCannotHaveInitializers(
- node.Initializer));
- }
- try
- {
- PushMember(node);
- PreProcessFieldInitializer(node);
- }
- finally
- {
- PopMember();
- }
- }
- else
- {
- if (null == node.Type)
- {
- node.Type = CreateTypeReference(node.LexicalInfo, TypeSystemServices.ObjectType);
- }
- }
- 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 = CreateTypeReference(node.LexicalInfo, MapNullToObject(initializerType));
- }
- else
- {
- AssertTypeCompatibility(node.Initializer, GetType(node.Type), initializerType);
- }
- }
- private TypeReference CreateTypeReference(LexicalInfo info, IType type)
- {
- TypeReference reference = CodeBuilder.CreateTypeReference(type);
- reference.LexicalInfo = info;
- return reference;
- }
- private 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 = GetExpressionType(assignment.Right);
- 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(
- initializer.LexicalInfo,
- CodeBuilder.CreateReference(node),
- initializer));
- node.Initializer = null;
- }
- Method CreateInitializerMethod(TypeDefinition type, string name, TypeMemberModifiers modifiers)
- {
- Method method = new Method(name);
- method.IsSynthetic = true;
- 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;
- }
- private Field GetFieldsInitializerInitializedField(TypeDefinition type)
- {
- string name = AstUtil.BuildUniqueTypeMemberName(type, "initialized");
- Field field= (Field) type.Members[name];
- if (null == field)
- {
- field = CodeBuilder.CreateField(name, TypeSystemServices.BoolType);
- field.Visibility = TypeMemberModifiers.Private;
- type.Members.Add(field);
- MarkVisited(field);
- }
- return field;
- }
- 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 (!type.HasStaticConstructor)
- {
- // when the class doesnt have a static constructor
- // yet, create one and use it as the static
- // field initializer method
- method = CodeBuilder.CreateStaticConstructor(type);
- }
- else
- {
- method = CreateInitializerMethod(type, methodName, TypeMemberModifiers.Static);
- AddInitializerToStaticConstructor(type, (InternalMethod)method.Entity);
- }
- }
- else
- {
- method = CreateInitializerMethod(type, methodName, TypeMemberModifiers.None);
- }
- type[methodName] = method;
- }
- return method;
- }
- void AddInitializerToStaticConstructor(TypeDefinition type, InternalMethod initializer)
- {
- GetStaticConstructor(type).Body.Insert(0,
- CodeBuilder.CreateMethodInvocation(initializer));
- }
- void AddInitializerToInstanceConstructors(TypeDefinition type, Method initializer)
- {
- int n = 0;
- //count number of non-static constructors
- foreach (TypeMember node in type.Members)
- {
- if (NodeType.Constructor == node.NodeType && !node.IsStatic)
- n++;
- }
- //if there is more than one we need $initialized$ guard check
- if (n > 1)
- AddInitializedGuardToInitializer(type, initializer);
- foreach (TypeMember node in type.Members)
- {
- if (NodeType.Constructor == node.NodeType && !node.IsStatic)
- {
- Constructor constructor = (Constructor) node;
- n = GetIndexAfterSuperInvocation(constructor.Body);
- foreach (Statement st in initializer.Body.Statements)
- {
- constructor.Body.Insert(n, (Statement) st.Clone());
- n++;
- }
- foreach (Local loc in initializer.Locals)
- {
- constructor.Locals.Add(loc);
- }
- }
- }
- }
- void AddInitializedGuardToInitializer(TypeDefinition type, Method initializer)
- {
- Field field = GetFieldsInitializerInitializedField(type);
- //run initializer code only if $initialized$ is false
- //hmm quasi-notation would be lovely here
- Block trueBlock = new Block();
- trueBlock.Add(new GotoStatement(LexicalInfo.Empty, new ReferenceExpression("___initialized___")));
- IfStatement cond = new IfStatement(CodeBuilder.CreateReference(field),
- trueBlock, null);
- initializer.Body.Insert(0, cond);
- //set $initialized$ field to true
- initializer.Body.Add(
- CodeBuilder.CreateFieldAssignment(field, new BoolLiteralExpression(true)));
- //label we're past the initializer
- initializer.Body.Add(
- new LabelStatement(LexicalInfo.Empty, "___initialized___"));
- }
- 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 GetStaticConstructor(TypeDefinition type)
- {
- Constructor constructor = type.GetStaticConstructor();
- if (null == constructor)
- {
- constructor = CodeBuilder.CreateStaticConstructor(type);
- }
- 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));
- }
- }
- //ECMA-335 Partition III Section 1.8.1.4
- //cannot call an instance method before super/self.
- void CheckInstanceMethodInvocationsWithinConstructor(Constructor ctor)
- {
- if (ctor.Body.Statements.Count == 0) return;
- foreach (Statement st in ctor.Body.Statements)
- {
- if (!(st is ExpressionStatement)) continue;
- MethodInvocationExpression mie = ((ExpressionStatement) st).Expression as MethodInvocationExpression;
- if (null == mie) continue;
- if (mie.Target is SelfLiteralExpression
- || mie.Target is SuperLiteralExpression)
- break;//okay we're done checking
- if (mie.Target is MemberReferenceExpression)
- {
- MemberReferenceExpression mre = (MemberReferenceExpression) mie.Target;
- if (mre.Target is SelfLiteralExpression
- || mre.Target is SuperLiteralExpression)
- {
- Error(CompilerErrorFactory.InstanceMethodInvocationBeforeInitialization(ctor, mre));
- }
- }
- }
- }
- 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));
- }
- }
- if (!entity.IsStatic)
- CheckInstanceMethodInvocationsWithinConstructor(node);
- }
- }
- 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 OnBlockExpression(BlockExpression node)
- {
- if (WasVisited(node)) return;
- MarkVisited(node);
- Method closure = CodeBuilder.CreateMethod(
- ClosureNameFor(node),
- Unknown.Default,
- ClosureModifiers());
- 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 TypeMemberModifiers ClosureModifiers()
- {
- TypeMemberModifiers modifiers = TypeMemberModifiers.Internal;
- if (_currentMethod.IsStatic)
- {
- modifiers |= TypeMemberModifiers.Static;
- }
- return modifiers;
- }
- private string ClosureNameFor(BlockExpression block)
- {
- string closureHint = (block["ClosureName"] as string) ?? "closure";
- return _currentMethod.Name + "$" + closureHint + "$" + _context.AllocIndex();
- }
- 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 = 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)
- {
- return null;
- }
- IMethod baseMethod = FindMethodOverride(entity, candidates);
- if (null != baseMethod)
- {
- EnsureRelatedNodeWasVisited(method, baseMethod);
- }
- return baseMethod;
- }
- private static IMethod FindMethodOverride(InternalMethod entity, IEntity candidates)
- {
- if (EntityType.Method == candidates.EntityType)
- {
- IMethod candidate = (IMethod)candidates;
- if (TypeSystemServices.CheckOverrideSignature(entity, candidate))
- {
- return candidate;
- }
- }
-
- if (EntityType.Ambiguous == candidates.EntityType)
- {
- IEntity[] entities = ((Ambiguous)candidates).Entities;
- foreach (IMethod candidate in entities)
- {
- if (TypeSystemServices.CheckOverrideSignature(entity, candidate))
- {
- return candidate;
- }
- }
- }
- 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)
- {
- CallableSignature baseSignature = TypeSystemServices.GetOverriddenSignature(baseMethod, entity);
- if (TypeSystemServices.IsUnknown(entity.ReturnType))
- {
- entity.Method.ReturnType = CodeBuilder.CreateTypeReference(entity.Method.LexicalInfo, baseSignature.ReturnType);
- }
- else if (baseSignature.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(node.LexicalInfo, 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);
- PostProcessMethod(node);
- }
- private void PostProcessMethod(Method node)
- {
- bool parentIsClass = node.DeclaringType.NodeType == NodeType.ClassDefinition;
- if (!parentIsClass) return;
- InternalMethod entity = (InternalMethod)GetEntity(node);
- if (TypeSystemServices.IsUnknown(entity.ReturnType))
- {
- TryToResolveReturnType(entity);
- }
- else
- {
- if (entity.IsGenerator)
- {
- CheckGeneratorReturnType(node, entity.ReturnType);
- CheckGeneratorYieldType(entity, entity.ReturnType);
- }
- }
- CheckGeneratorCantReturnValues(entity);
- }
- void CheckGeneratorCantReturnValues(InternalMethod entity)
- {
- if (!entity.IsGenerator) return;
- if (null == entity.ReturnExpressions) return;
- foreach (Expression e in entity.ReturnExpressions)
- {
- Error(CompilerErrorFactory.GeneratorCantReturnValue(e));
- }
- }
- void CheckGeneratorReturnType(Method method, IType returnType)
- {
- bool validReturnType =
- (TypeSystemServices.IEnumerableType == returnType ||
- TypeSystemServices.IEnumeratorType == returnType ||
- TypeSystemServices.IsSystemObject(returnType) ||
- CheckGenericGeneratorReturnType(returnType));
- if (!validReturnType)
- {
- Error(CompilerErrorFactory.InvalidGeneratorReturnType(method.ReturnType));
- }
- }
- bool CheckGenericGeneratorReturnType(IType returnType)
- {
- return returnType.ConstructedInfo != null &&
- (returnType.ConstructedInfo.GenericDefinition == TypeSystemServices.IEnumerableGenericType ||
- returnType.ConstructedInfo.GenericDefinition == TypeSystemServices.IEnumeratorGenericType);
- }
- void CheckGeneratorYieldType(InternalMethod method, IType returnType)
- {
- if (CheckGenericGeneratorReturnType(returnType))
- {
- IType returnElementType = returnType.ConstructedInfo.GenericArguments[0];
- foreach (Expression yieldExpression in method.YieldExpressions)
- {
- IType yieldType = yieldExpression.ExpressionType;
- if (!returnElementType.IsAssignableFrom(yieldType) &&
- !TypeSystemServices.CanBeReachedByDownCastOrPromotion(returnElementType, yieldType))
- {
- Error(CompilerErrorFactory.YieldTypeDoesNotMatchReturnType(
- yieldExpression, yieldType.ToString(), returnElementType.ToString()));
- }
- }
- }
- }
- 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;
- // Make method return a generic IEnumerable
- IType itemType = (IType)method["GeneratorItemType"];
- if (TypeSystemServices.VoidType == itemType)
- {
- // circunvent exception in MakeGenericType
- method.ReturnType = CodeBuilder.CreateTypeReference(TypeSystemServices.ErrorEntity);
- return;
- }
- IType returnType = GetGeneratorReturnType(itemType);
- method.ReturnType = CodeBuilder.CreateTypeReference(returnType);
- }
- protected virtual IType GetGeneratorReturnType(IType itemType)
- {
- IType enumerableType = TypeSystemServices.IEnumerableGenericType;
- return enumerableType.GenericInfo.ConstructType(itemType);
- }
- void TryToResolveReturnType(InternalMethod entity)
- {
- if (entity.IsGenerator)
- {
- ResolveGeneratorReturnType(entity);
- }
- else
- {
- if (CanResolveReturnType(entity))
- {
- ResolveReturnType(entity);
- }
- }
- }
- override public void OnSuperLiteralExpression(SuperLiteralExpression node)
- {
- if (!AstUtil.IsTargetOfMethodInvocation(node))
- {
- node.ExpressionType = _currentMethod.DeclaringType.BaseType;
- return;
- }
- if (EntityType.Constructor == _currentMethod.EntityType)
- {
- // TODO: point to super ctor
- node.Entity = _currentMethod;
- return;
- }
- if (null == _currentMethod.Overriden)
- {
- Error(node,
- CompilerErrorFactory.MethodIsNotOverride(node, _currentMethod.ToString()));
- return;
- }
- node.Entity = _currentMethod;
- }
- 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<args.Count; ++i)
- {
- IType newType = GetConcreteExpressionType(args[i]);
- if (type == newType)
- {
- continue;
- }
- type = GetMostGenericType(type, newType);
- if (TypeSystemServices.IsSystemObject(type))
- {
- break;
- }
- }
- return type;
- }
- override public void OnBoolLiteralExpression(BoolLiteralExpression node)
- {
- BindExpressionType(node, TypeSystemServices.BoolType);
- }
- override public void OnTimeSpanLiteralExpression(TimeSpanLiteralExpression node)
- {
- BindExpressionType(node, TypeSystemServices.TimeSpanType);
- }
- override public void OnIntegerLiteralExpression(IntegerLiteralExpression node)
- {
- if (node.IsLong)
- {
- BindExpressionType(node, TypeSystemServices.LongType);
- }
- else
- {
- BindExpressionType(node, TypeSystemServices.IntType);
- }
- }
- override public void OnDoubleLiteralExpression(DoubleLiteralExpression node)
- {
- BindExpressionType(node, node.IsSingle ? TypeSystemServices.SingleType : TypeSystemServices.DoubleType);
- }
- override public void OnStringLiteralExpression(StringLiteralExpression node)
- {
- BindExpressionType(node, TypeSystemServices.StringType);
- }
- override public void OnCharLiteralExpression(CharLiteralExpression node)
- {
- string value = node.Value;
- if (null == value || 1 != value.Length)
- {
- Errors.Add(CompilerErrorFactory.InvalidCharLiteral(node, value));
- }
- BindExpressionType(node, TypeSystemServices.CharType);
- }
- IEntity[] GetSetMethods(IEntity[] entities)
- {
- List setMethods = new List();
- for (int i=0; i<entities.Length; ++i)
- {
- IProperty property = entities[i] as IProperty;
- if (null != property)
- {
- IMethod setter = property.GetSetMethod();
- if (null != setter)
- {
- setMethods.AddUnique(setter);
- }
- }
- }
- return ToEntityArray(setMethods);
- }
- IEntity[] GetGetMethods(IEntity[] entities)
- {
- List getMethods = new List();
- for (int i=0; i<entities.Length; ++i)
- {
- IProperty property = entities[i] as IProperty;
- if (null != property)
- {
- IMethod getter = property.GetGetMethod();
- if (null != getter)
- {
- getMethods.AddUnique(getter);
- }
- }
- }
- return ToEntityArray(getMethods);
- }
- private static IEntity[] ToEntityArray(List entities)
- {
- return (IEntity[])entities.ToArray(new IEntity[entities.Count]);
- }
- void CheckNoComplexSlicing(SlicingExpression node)
- {
- if (AstUtil.IsComplexSlicing(node))
- {
- NotImplemented(node, "complex slicing");
- }
- }
- protected MethodInvocationExpression CreateEquals(BinaryExpression node)
- {
- return CodeBuilder.CreateMethodInvocation(RuntimeServices_EqualityOperator, node.Left, node.Right);
- }
- IntegerLiteralExpression CreateIntegerLiteral(long value)
- {
- IntegerLiteralExpression expression = new IntegerLiteralExpression(value);
- Visit(expression);
- return expression;
- }
- bool CheckComplexSlicingParameters(SlicingExpression node)
- {
- foreach (Slice slice in node.Indices)
- {
- if (!CheckComplexSlicingParameters(slice))
- {
- return false;
- }
- }
- return true;
- }
- bool CheckComplexSlicingParameters(Slice node)
- {
- if (null != node.Step)
- {
- NotImplemented(node, "slicing step");
- return false;
- }
- if (OmittedExpression.Default == node.Begin)
- {
- node.Begin = CreateIntegerLiteral(0);
- }
- else
- {
- if (!AssertTypeCompatibility(node.Begin, TypeSystemServices.IntType, GetExpressionType(node.Begin)))
- {
- return false;
- }
- }
- if (null != node.End && OmittedExpression.Default != node.End)
- {
- if (!AssertTypeCompatibility(node.End, TypeSystemServices.IntType, GetExpressionType(node.End)))
- {
- return false;
- }
- }
- return true;
- }
- void BindComplexListSlicing(SlicingExpression node)
- {
- Slice slice = node.Indices[0];
- if (CheckComplexSlicingParameters(slice))
- {
- MethodInvocationExpression mie = null;
- if (null == slice.End || slice.End == OmittedExpression.Default)
- {
- mie = CodeBuilder.CreateMethodInvocation(node.Target, List_GetRange1);
- mie.Arguments.Add(slice.Begin);
- }
- else
- {
- mie = CodeBuilder.CreateMethodInvocation(node.Target, List_GetRange2);
- mie.Arguments.Add(slice.Begin);
- mie.Arguments.Add(slice.End);
- }
- node.ParentNode.Replace(node, mie);
- }
- }
- void BindComplexArraySlicing(SlicingExpression node)
- {
- if (AstUtil.IsLhsOfAssignment(node))
- {
- return;
- }
- if (CheckComplexSlicingParameters(node))
- {
- if (node.Indices.Count > 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 CreateSelfReference();
- }
- 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)
- {
- BlockExpression block = new BlockExpression(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;
- IType itemType = GetGeneratorItemType(entity);
- BooClassBuilder builder = CreateGeneratorSkeleton(method, method, itemType);
- method.DeclaringType.Members.Add(builder.ClassDefinition);
- // TypeSystemServices.AddCompilerGeneratedType(builder.ClassDefinition);
- }
- private IType GetGeneratorItemType(InternalMethod entity)
- {
- IType itemType = null;
- if (CheckGenericGeneratorReturnType(entity.ReturnType))
- {
- itemType = entity.ReturnType.ConstructedInfo.GenericArguments[0];
- }
- if (itemType == null)
- {
- ExpressionCollection yieldExpressions = entity.YieldExpressions;
- itemType = yieldExpressions.Count > 0
- ? GetMostGenericType(yieldExpressions)
- : TypeSystemServices.ObjectType;
- }
- return itemType;
- }
- BooClassBuilder CreateGeneratorSkeleton(GeneratorExpression node)
- {
- BooClassBuilder builder = CreateGeneratorSkeleton(node, _currentMethod.Method, GetConcreteExpressionType(node.Expression));
- _currentMethod.Method.DeclaringType.Members.Add(builder.ClassDefinition);
- return builder;
- }
- protected IType GetConstructedType(IType genericType, IType argType)
- {
- return genericType.GenericInfo.ConstructType(argType);
- }
- BooClassBuilder CreateGeneratorSkeleton(Node sourceNode, Method method, IType generatorItemType)
- {
- // create the class skeleton for type inference to work
- BooClassBuilder builder = CodeBuilder.CreateClass(
- string.Format("{0}${1}", method.Name, _context.AllocIndex()),
- TypeMemberModifiers.Internal|TypeMemberModifiers.Final);
- builder.LexicalInfo = sourceNode.LexicalInfo;
- builder.AddAttribute(CodeBuilder.CreateAttribute(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute)));
- BooMethodBuilder getEnumeratorBuilder = null;
- if (generatorItemType != TypeSystemServices.VoidType)
- {
- builder.AddBaseType(
- TypeSystemServices.Map(typeof(GenericGenerator<>)).GenericInfo.ConstructType(generatorItemType));
- getEnumeratorBuilder = builder.AddVirtualMethod(
- "GetEnumerator",
- TypeSystemServices.IEnumeratorGenericType.GenericInfo.ConstructType(generatorItemType));
- 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 = GetDeclarationType(node);
- AssertDeclarationName(node.Declaration);
- IEntity localInfo = DeclareLocal(node, node.Declaration.Name, type);
- if (null != node.Initializer)
- {
- IType itype = GetExpressionType(node.Initializer);
- AssertTypeCompatibility(node.Initializer, type, itype);
- if (TypeSystemServices.IsNullable(type) && !TypeSystemServices.IsNullable(itype))
- {
- BindNullableInitializer(node, node.Initializer, type);
- }
- node.ReplaceBy(
- new ExpressionStatement(
- CodeBuilder.CreateAssignment(
- node.LexicalInfo,
- CodeBuilder.CreateReference(localInfo),
- node.Initializer)));
- }
- else
- {
- node.ReplaceBy(
- new ExpressionStatement(
- CreateDefaultLocalInitializer(node, localInfo)));
- }
- }
- private IType GetDeclarationType(DeclarationStatement node)
- {
- if (null != node.Declaration.Type) return GetType(node.Declaration.Type);
- return InferDeclarationType(node);
- }
- private IType InferDeclarationType(DeclarationStatement node)
- {
- if (null == node.Initializer) return TypeSystemServices.ObjectType;
- // 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).
- return GetConcreteExpressionType(node.Initializer);
- }
- 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.SelfIsNotValidInStaticMember(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 = CodeBuilder.CreateField(fieldName, type);
- field.Modifiers = TypeMemberModifiers.Internal|TypeMemberModifiers.Static;
- field.Initializer = node;
- _currentMethod.Method.DeclaringType.Members.Add(field);
- parent.Replace(node, CodeBuilder.CreateReference(field));
- AddFieldInitializerToStaticConstructor(0, field);
- }
- override public void LeaveGenericReferenceExpression(GenericReferenceExpression node)
- {
- if (node.Target.Entity == null || TypeSystemServices.IsError(node.Target.Entity))
- {
- BindExpressionType(node, TypeSystemServices.ErrorEntity);
- return;
- }
- IEntity entity = NameResolutionService.ResolveGenericReferenceExpression(node, node.Target.Entity);
- Bind(node, entity);
- if (entity.EntityType == EntityType.Type)
- {
- BindTypeReferenceExpressionType(node, (IType)entity);
- }
- else if (entity.EntityType == EntityType.Method)
- {
- if (null == (node.Target as MemberReferenceExpression)) //no self.
- {
- MemberReferenceExpression target =
- CodeBuilder.MemberReferenceForEntity(
- CreateSelfReference(),
- entity);
- node.Replace(node.Target, target);
- }
- BindExpressionType(node, ((IMethod)entity).Type);
- }
- }
- override public void OnReferenceExpression(ReferenceExpression node)
- {
- if (AlreadyBound(node)) return;
- IEntity entity = ResolveName(node, node.Name);
- if (null == entity)
- {
- Error(node);
- return;
- }
- // 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)
- {
- if (IsExtensionMethod(member))
- {
- Bind(node, member);
- return;
- }
- ResolveMemberInfo(node, member);
- return;
- }
- EnsureRelatedNodeWasVisited(node, entity);
- node.Entity = entity;
- PostProcessReferenceExpression(node);
- }
- private static bool AlreadyBound(ReferenceExpression node)
- {
- return null != node.ExpressionType;
- }
- 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:
- {
- BindTypeReferenceExpressionType(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 (tag is IType)
- {
- BindTypeReferenceExpressionType(node, (IType)tag);
- 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 BindTypeReferenceExpressionType(Expression node, IType type)
- {
- if (IsStandaloneReference(node))
- {
- BindExpressionType(node, TypeSystemServices.TypeType);
- }
- else
- {
- BindExpressionType(node, type);
- }
- }
- 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)
- {
- EntityType et = (!AstUtil.IsTargetOfMethodInvocation(node)) ? EntityType.Any : EntityType.Method;
- Error(node,
- CompilerErrorFactory.MemberNotFound(node,
- (((IEntity)ns).ToString()),
- NameResolutionService.GetMostSimilarMemberName(ns, node.Name, et)));
- }
- 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)
- {
- IAccessibleMember accessible = member as IAccessibleMember;
- if (null != accessible && !IsAccessible(accessible))
- {
- IEntity extension = NameResolutionService.ResolveExtension(ns, node.Name);
- if (null != extension) return extension;
- }
- 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);
- if (EntityType.Namespace == member.EntityType)
- {
- string ns = null;
- foreach (Import import in _currentModule.Imports)
- {
- if (import.NamespaceUsed) continue;
- if (null == ns) ns = node.ToCodeString();
- if (import.Namespace == ns)
- {
- import.NamespaceUsed = true;
- break;
- }
- }
- }
- IMember memberInfo = member as IMember;
- if (null != memberInfo)
- {
- if (!AssertTargetContext(node, memberInfo))
- {
- Error(node);
- return;
- }
- if (EntityType.Method != memberInfo.EntityType)
- {
- 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)
- {
- IEntity resolved = ResolveAmbiguousReferenceByAccessibility(candidates);
- Ambiguous accessibleCandidates = resolved as Ambiguous;
- if (accessibleCandidates != null &&
- !AstUtil.IsTargetOfSlicing(node) &&
- !AstUtil.IsLhsOfAssignment(node))
- {
- if (accessibleCandidates.AllEntitiesAre(EntityType.Property))
- {
- return ResolveAmbiguousPropertyReference(node, accessibleCandidates, EmptyExpressionCollection);
- }
- else if (accessibleCandidates.AllEntitiesAre(EntityType.Method))
- {
- return ResolveAmbiguousMethodReference(node, accessibleCandidates, EmptyExpressionCollection);
- }
- else if (accessibleCandidates.AllEntitiesAre(EntityType.Type))
- {
- return ResolveAmbiguousTypeReference(node, accessibleCandidates);
- }
- }
- return resolved;
- }
- 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 IEntity ResolveAmbiguousTypeReference(ReferenceExpression node, Ambiguous candidates)
- {
- bool isGenericReference = (node.ParentNode is GenericReferenceExpression);
- List matches = new List();
- foreach (IEntity candidate in candidates.Entities)
- {
- IType type = candidate as IType;
- bool isGenericType = (type != null && type.GenericInfo != null);
- if (isGenericType == isGenericReference)
- {
- matches.Add(candidate);
- }
- }
- if (matches.Count == 1)
- {
- Bind(node, (IEntity)matches[0]);
- }
- else
- {
- Bind(node, new Ambiguous(matches));
- }
- return node.Entity;
- }
- private IEntity ResolveAmbiguousReferenceByAccessibility(Ambiguous candidates)
- {
- List newEntities = new List();
- foreach (IEntity entity in candidates.Entities)
- {
- if (!IsInaccessible(entity))
- {
- newEntities.Add(entity);
- }
- }
- if (newEntities.Count == 1)
- {
- return (IEntity)newEntities[0];
- }
- return new Ambiguous(newEntities);
- }
- private int GetIndex(IEntity[] entities, IEntity entity)
- {
- for (int i=0; i<entities.Length; ++i)
- {
- if (entities[i] == entity) return i;
- }
- throw new ArgumentException("entity");
- }
- override public void LeaveUnlessStatement(UnlessStatement node)
- {
- node.Condition = AssertBoolContext(node.Condition);
- }
- override public void LeaveIfStatement(IfStatement node)
- {
- node.Condition = AssertBoolContext(node.Condition);
- }
- override public void LeaveConditionalExpression(ConditionalExpression node)
- {
- node.Condition = AssertBoolContext(node.Condition);
- IType trueType = GetExpressionType(node.TrueValue);
- IType falseType = GetExpressionType(node.FalseValue);
- BindExpressionType(node, GetMostGenericType(trueType, falseType));
- }
- override public bool EnterWhileStatement(WhileStatement node)
- {
- return true;
- }
- override public void LeaveWhileStatement(WhileStatement node)
- {
- node.Condition = AssertBoolContext(node.Condition);
- }
- override public void LeaveYieldStatement(YieldStatement node)
- {
- if (EntityType.Constructor == _currentMethod.EntityType)
- {
- Error(CompilerErrorFactory.YieldInsideConstructor(node));
- }
- else
- {
- _currentMethod.AddYieldStatement(node);
- }
- }
- override public void LeaveReturnStatement(ReturnStatement node)
- {
- if (null == node.Expression) return;
- // forces anonymous types to be correctly
- // instantiated
- IType expressionType = GetConcreteExpressionType(node.Expression);
- if (TypeSystemServices.VoidType == expressionType
- && node.ContainsAnnotation(OptionalReturnStatementAnnotation))
- {
- node.ParentNode.Replace(
- node,
- new ExpressionStatement(node.Expression));
- return;
- }
- IType returnType = _currentMethod.ReturnType;
- if (TypeSystemServices.IsUnknown(returnType))
- {
- _currentMethod.AddReturnExpression(node.Expression);
- }
- else
- {
- AssertTypeCompatibility(node.Expression, returnType, expressionType);
- }
- }
- protected Expression GetCorrectIterator(Expression iterator)
- {
- IType type = GetExpressionType(iterator);
- if (TypeSystemServices.IsError(type))
- {
- return iterator;
- }
- if (!TypeSystemServices.IEnumerableType.IsAssignableFrom(type) &&
- !TypeSystemServices.IEnumeratorType.IsAssignableFrom(type))
- {
- if (IsRuntimeIterator(type))
- {
- if (IsTextReader(type))
- {
- return CodeBuilder.CreateMethodInvocation(TextReaderEnumerator_lines, iterator);
- }
- else
- {
- return CodeBuilder.CreateMethodInvocation(RuntimeServices_GetEnumerable, iterator);
- }
- }
- else
- {
- IMethod method = ResolveGetEnumerator(iterator, type);
- if (null == method)
- {
- Error(CompilerErrorFactory.InvalidIteratorType(iterator, type.ToString()));
- }
- else
- {
- return CodeBuilder.CreateMethodInvocation(iterator, method);
- }
- }
- }
- return iterator;
- }
- IMethod ResolveGetEnumerator(Node sourceNode, IType type)
- {
- IMethod method = ResolveMethod(type, "GetEnumerator");
- if (null != method)
- {
- EnsureRelatedNodeWasVisited(sourceNode, method);
- if (0 == method.GetParameters().Length &&
- method.ReturnType.IsSubclassOf(TypeSystemServices.IEnumeratorType))
- {
- return method;
- }
- }
- return null;
- }
- /// <summary>
- /// Process a iterator and its declarations and returns a new iterator
- /// expression if necessary.
- /// </summary>
- 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);
- Visit(node.OrBlock);
- Visit(node.ThenBlock);
- 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;
- GetDeclarationType(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,
- Exception_StringConstructor,
- node.Exception);
- }
- else if (!TypeSystemServices.IsValidException(exceptionType))
- {
- Error(CompilerErrorFactory.InvalidRaiseArgument(node.Exception,
- exceptionType.ToString()));
- }
- }
- override public void OnExceptionHandler(ExceptionHandler node)
- {
- bool untypedException = (node.Flags & ExceptionHandlerFlags.Untyped) == ExceptionHandlerFlags.Untyped;
- bool anonymousException = (node.Flags & ExceptionHandlerFlags.Anonymous) == ExceptionHandlerFlags.Anonymous;
- bool filterHandler = (node.Flags & ExceptionHandlerFlags.Filter) == ExceptionHandlerFlags.Filter;
- if (untypedException)
- {
- // If untyped, set the handler to except System.Exception
- node.Declaration.Type = CodeBuilder.CreateTypeReference(TypeSystemServices.ExceptionType);
- }
- else
- {
- Visit(node.Declaration.Type);
- // Require typed exception handlers to except only
- // exceptions at least as derived as System.Exception
- if(!TypeSystemServices.IsValidException(GetType(node.Declaration.Type)))
- {
- Errors.Add(CompilerErrorFactory.InvalidExceptArgument(node.Declaration.Type, GetType(node.Declaration.Type).FullName));
- }
- }
- if(!anonymousException)
- {
- // If the exception is not anonymous, place it into a
- // local variable and enter a new namespace
- node.Declaration.Entity = DeclareLocal(node.Declaration, node.Declaration.Name, GetType(node.Declaration.Type), true);
- EnterNamespace(new DeclarationsNamespace(CurrentNamespace, TypeSystemServices, node.Declaration));
- }
- try
- {
- // The filter handler has access to the exception if it
- // is not anonymous, so it is protected to ensure
- // any exception in the filter condition (a big no-no)
- // will still clean up the namespace if necessary
- if (filterHandler)
- {
- Visit(node.FilterCondition);
- }
- Visit(node.Block);
- }
- finally
- {
- // Clean up the namespace if necessary
- if(!anonymousException)
- {
- LeaveNamespace();
- }
- }
- }
- protected virtual bool IsValidIncrementDecrementOperand(Expression e)
- {
- IType type = GetExpressionType(e);
- if (TypeSystemServices.IsNullable(type))
- {
- type = TypeSystemServices.GetNullableUnderlyingType(type);
- }
- 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) || type.IsEnum;
- }
- 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)
- {
- if (IsEnumOperation(node))
- {
- BindEnumOperation(node);
- return;
- }
- 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.InPlaceModulus:
- case BinaryOperatorType.InPlaceBitwiseOr:
- case BinaryOperatorType.InPlaceBitwiseAnd:
- case BinaryOperatorType.InPlaceExclusiveOr:
- {
- 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));
- }
- bool IsNullableOperation(BinaryExpression node)
- {
- if (null == node.Left.ExpressionType || null == node.Right.ExpressionType)
- {
- return false;
- }
- return TypeSystemServices.IsNullable(GetExpressionType(node.Left))
- || TypeSystemServices.IsNullable(GetExpressionType(node.Right));
- }
- bool IsEnumOperation(BinaryExpression node)
- {
- switch (node.Operator)
- {
- case BinaryOperatorType.Addition:
- case BinaryOperatorType.Subtraction:
- case BinaryOperatorType.BitwiseAnd:
- case BinaryOperatorType.BitwiseOr:
- case BinaryOperatorType.ExclusiveOr:
- IType lhs = GetExpressionType(node.Left);
- IType rhs = GetExpressionType(node.Right);
- if (lhs.IsEnum) return IsValidEnumOperand(lhs, rhs);
- if (rhs.IsEnum) return IsValidEnumOperand(rhs, lhs);
- break;
- }
- return false;
- }
- bool IsValidEnumOperand(IType expected, IType actual)
- {
- if (expected == actual) return true;
- if (actual.IsEnum) return true;
- return TypeSystemServices.IsIntegerNumber(actual);
- }
- void BindEnumOperation(BinaryExpression node)
- {
- IType lhs = GetExpressionType(node.Left);
- IType rhs = GetExpressionType(node.Right);
- switch(node.Operator)
- {
- case BinaryOperatorType.Addition:
- if (lhs.IsEnum != rhs.IsEnum)
- {
- BindExpressionType(node, lhs.IsEnum ? lhs : rhs);
- return;
- }
- break;
- case BinaryOperatorType.Subtraction:
- if (lhs == rhs)
- {
- BindExpressionType(node, TypeSystemServices.IntType);
- return;
- }
- else if (lhs.IsEnum && !rhs.IsEnum)
- {
- BindExpressionType(node, lhs);
- return;
- }
- break;
- case BinaryOperatorType.BitwiseAnd:
- case BinaryOperatorType.BitwiseOr:
- case BinaryOperatorType.ExclusiveOr:
- if (lhs == rhs)
- {
- BindExpressionType(node, lhs);
- return;
- }
- break;
- }
- if (!ResolveOperator(node))
- {
- InvalidOperatorForTypes(node);
- }
- }
- 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)
- {
- if (BindNullableComparison(node))
- {
- return;
- }
- IType lhs = GetExpressionType(node.Left);
- IType rhs = GetExpressionType(node.Right);
- if (IsPrimitiveComparison(lhs, rhs))
- {
- BindExpressionType(node, TypeSystemServices.BoolType);
- return;
- }
- if (lhs.IsEnum || rhs.IsEnum)
- {
- if (lhs == rhs || IsPrimitiveNumber(rhs) || IsPrimitiveNumber(lhs))
- {
- BindExpressionType(node, TypeSystemServices.BoolType);
- }
- else
- {
- if (!ResolveOperator(node))
- {
- InvalidOperatorForTypes(node);
- }
- }
- return;
- }
- 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;
- }
- }
- }
- }
- private bool IsPrimitiveComparison(IType lhs, IType rhs)
- {
- if (IsPrimitiveNumberOrChar(lhs) && IsPrimitiveNumberOrChar(rhs)) return true;
- if (IsBool(lhs) && IsBool(rhs)) return true;
- return false;
- }
- private bool IsPrimitiveNumberOrChar(IType lhs)
- {
- return IsPrimitiveNumber(lhs) || IsChar(lhs);
- }
- private bool IsBool(IType lhs)
- {
- return TypeSystemServices.BoolType == lhs;
- }
- private 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).Select(IsPublicEvent);
- 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);
- break;
- }
- }
- }
- bool ProcessSwitchInvocation(MethodInvocationExpression node)
- {
- if (BuiltinFunction.Switch != node.Target.Entity) return false;
- BindSwitchLabelReferences(node);
- if (CheckSwitchArguments(node)) return true;
- Error(node, CompilerErrorFactory.InvalidSwitch(node.Target));
- return true;
- }
- 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<args.Count; ++i)
- {
- if (NodeType.ReferenceExpression != args[i].NodeType)
- {
- return false;
- }
- }
- return true;
- }
- }
- return false;
- }
- void ProcessEvalInvocation(MethodInvocationExpression node)
- {
- if (node.Arguments.Count > 0)
- {
- int allButLast = node.Arguments.Count-1;
- for (int i=0; i<allButLast; ++i)
- {
- AssertHasSideEffect(node.Arguments[i]);
- }
- BindExpressionType(node, GetConcreteExpressionType(node.Arguments[-1]));
- }
- else
- {
- BindExpressionType(node, TypeSystemServices.VoidType);
- }
- }
- void ProcessAddressOfInvocation(MethodInvocationExpression node)
- {
- if (node.Arguments.Count != 1)
- {
- Error(node, CompilerErrorFactory.MethodArgumentCount(node.Target, "__addressof__", 1));
- }
- else
- {
- Expression arg = node.Arguments[0];
- EntityType type = GetEntity(arg).EntityType;
- if (EntityType.Method != type)
- {
- ReferenceExpression reference = arg as ReferenceExpression;
- if (null != reference && EntityType.Ambiguous == type)
- {
- Error(node, CompilerErrorFactory.AmbiguousReference(arg, reference.Name, ((Ambiguous)arg.Entity).Entities));
- }
- else
- {
- Error(node, CompilerErrorFactory.MethodReferenceExpected(arg));
- }
- }
- else
- {
- BindExpressionType(node, TypeSystemServices.IntPtrType);
- }
- }
- }
- void ProcessLenInvocation(MethodInvocationExpression node)
- {
- if ((node.Arguments.Count < 1) || (node.Arguments.Count > 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);
- if (ProcessSwitchInvocation(node)) return;
- if (ProcessMetaMethodInvocation(node)) return;
- Visit(node.Arguments);
- if (TypeSystemServices.IsError(node.Target)
- || TypeSystemServices.IsErrorAny(node.Arguments))
- {
- Error(node);
- return;
- }
- IEntity targetEntity = node.Target.Entity;
- if (null == targetEntity)
- {
- ProcessGenericMethodInvocation(node);
- return;
- }
- if (IsOrContainsBooExtensionMethod(targetEntity))
- {
- ProcessExtensionMethodInvocation(node, targetEntity);
- return;
- }
- ProcessMethodInvocationExpression(node, targetEntity);
- }
- private bool ProcessMetaMethodInvocation(MethodInvocationExpression node)
- {
- IEntity targetEntity = node.Target.Entity;
- if (null == targetEntity) return false;
- if (!IsOrContainMetaMethod(targetEntity)) return false;
- object[] arguments = GetMetaMethodInvocationArguments(node);
- Type[] argumentTypes = MethodResolver.GetArgumentTypes(arguments);
- MethodResolver resolver = new MethodResolver(argumentTypes);
- CandidateMethod method = resolver.ResolveMethod(EnumerateMetaMethods(targetEntity));
- if (null == method) return false;
- // TODO: cache emitted dispatchers
- MethodDispatcherEmitter emitter = new MethodDispatcherEmitter(method, argumentTypes);
- Node replacement = (Node)emitter.Emit()(null, arguments);
- ReplaceMetaMethodInvocationSite(node, replacement);
- return true;
- }
- private static object[] GetMetaMethodInvocationArguments(MethodInvocationExpression node)
- {
- if (node.NamedArguments.Count == 0) return node.Arguments.ToArray();
- List arguments = new List();
- arguments.Add(node.NamedArguments.ToArray());
- arguments.Extend(node.Arguments);
- return arguments.ToArray();
- }
- private void ReplaceMetaMethodInvocationSite(MethodInvocationExpression node, Node replacement)
- {
- if (replacement == null || replacement is Statement)
- {
- if (node.ParentNode.NodeType != NodeType.ExpressionStatement)
- {
- NotImplemented(node, "Cant use an statement where an expression is expected.");
- }
- Node statementParent = node.ParentNode.ParentNode;
- statementParent.Replace(node.ParentNode, replacement);
- }
- else
- {
- node.ParentNode.Replace(node, replacement);
- }
- Visit(replacement);
- }
- private System.Collections.Generic.IEnumerable<System.Reflection.MethodInfo> EnumerateMetaMethods(IEntity entity)
- {
- if (entity.EntityType == EntityType.Method)
- {
- yield return GetMethodInfo(entity);
- }
- else
- {
- foreach (IEntity item in ((Ambiguous)entity).Entities)
- {
- yield return GetMethodInfo(item);
- }
- }
- }
- private static MethodInfo GetMethodInfo(IEntity entity)
- {
- return (MethodInfo)((ExternalMethod) entity).MethodInfo;
- }
- private bool IsOrContainMetaMethod(IEntity entity)
- {
- switch (entity.EntityType)
- {
- case EntityType.Ambiguous:
- return ((Ambiguous) entity).Any(IsMetaMethod);
- case EntityType.Method:
- return IsMetaMethod(entity);
- }
- return false;
- }
- private static bool IsMetaMethod(IEntity entity)
- {
- ExternalMethod m = entity as ExternalMethod;
- if (m == null) return false;
- return m.IsMeta;
- }
- 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) return;
- 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 bool ProcessMethodInvocationWithInvalidParameters(MethodInvocationExpression node, IMethod targetMethod)
- {
- return false;
- }
- protected virtual void ProcessMethodInvocation(MethodInvocationExpression node, IEntity targetEntity)
- {
- IMethod targetMethod = (IMethod)targetEntity;
- // Infer generic arguments if this is a generic, non-constructed method
- if (targetMethod.GenericInfo != null)
- {
- targetMethod = InferGenericMethodInvocation(node, targetMethod);
- if (targetMethod == null) return;
- }
- if (!CheckParameters(targetMethod.CallableType, node.Arguments, false) ||
- !CheckGenericMethodInvocation(node, targetMethod) ||
- !IsAccessible(targetMethod))
- {
- if (TryToProcessAsExtensionInvocation(node)) return;
- if (ProcessMethodInvocationWithInvalidParameters(node, targetMethod)) return;
- AssertParameters(node, targetMethod, node.Arguments);
- }
- AssertTargetContext(node.Target, targetMethod);
- NamedArgumentsNotAllowed(node);
- EnsureRelatedNodeWasVisited(node.Target, targetMethod);
- BindExpressionType(node, GetInferredType(targetMethod));
- ApplyBuiltinMethodTypeInference(node, targetMethod);
- }
- private IMethod InferGenericMethodInvocation(MethodInvocationExpression node, IMethod targetMethod)
- {
- IType[] inferredArguments =
- TypeSystemServices.GenericsServices.InferMethodGenericArguments(targetMethod, node.Arguments);
- if (inferredArguments == null)
- {
- Error(node, CompilerErrorFactory.CannotInferGenericMethodArguments(
- node, targetMethod));
- return null;
- }
- IMethod constructedMethod = targetMethod.GenericInfo.ConstructMethod(inferredArguments);
- Bind(node.Target, constructedMethod);
- BindExpressionType(node, GetInferredType(constructedMethod));
-
- return constructedMethod;
- }
- private bool CheckGenericMethodInvocation(MethodInvocationExpression node, IMethod targetMethod)
- {
- // Ensure that a constructed method (whether explicit or inferred)
- // satisfies its generic constraints
- if (targetMethod.ConstructedInfo != null)
- {
- return TypeSystemServices.GenericsServices.CheckGenericConstruction(
- node,
- targetMethod.ConstructedInfo.GenericDefinition,
- targetMethod.ConstructedInfo.GenericArguments,
- Errors);
- }
- return true;
- }
- private bool IsAccessible(IAccessibleMember method)
- {
- return GetAccessibilityChecker().IsAccessible(method);
- }
- private IAccessibilityChecker GetAccessibilityChecker()
- {
- if (null == _currentMethod) return AccessibilityChecker.Global;
- return new AccessibilityChecker(CurrentTypeDefinition);
- }
- private TypeDefinition CurrentTypeDefinition
- {
- get { return _currentMethod.Method.DeclaringType; }
- }
- 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 IsExtensionMethod(IEntity entity)
- {
- if (EntityType.Method != entity.EntityType) return false;
- return ((IMethod)entity).IsExtension;
- }
- private bool IsOrContainsBooExtensionMethod(IEntity entity)
- {
- if (entity.EntityType == EntityType.Ambiguous) return IsBooExtensionMethod(((Ambiguous)entity).Entities[0]);
- return IsBooExtensionMethod(entity);
- }
- private bool IsBooExtensionMethod(IEntity entity)
- {
- if (EntityType.Method != entity.EntityType) return false;
- return ((IMethod)entity).IsBooExtension;
- }
- private void PostNormalizationExtensionInvocation(MethodInvocationExpression node, IMethod targetMethod)
- {
- node.Target = CodeBuilder.CreateMethodReference(node.Target.LexicalInfo, targetMethod);
- }
- private void PreNormalizeExtensionInvocation(MethodInvocationExpression node)
- {
- node.Arguments.Insert(0, EnsureMemberReferenceForExtension(node).Target);
- }
- private MemberReferenceExpression EnsureMemberReferenceForExtension(MethodInvocationExpression node)
- {
- MemberReferenceExpression memberRef = node.Target as MemberReferenceExpression;
- if (null != memberRef) return memberRef;
- node.Target = memberRef = CodeBuilder.MemberReferenceForEntity(
- CreateSelfReference(),
- GetEntity(node.Target));
- return memberRef;
- }
- private SelfLiteralExpression CreateSelfReference()
- {
- return CodeBuilder.CreateSelfReference(CurrentType);
- }
- protected virtual bool IsDuckTyped(IMember entity)
- {
- return entity.IsDuckTyped;
- }
- private IType GetInferredType(IMethod entity)
- {
- return IsDuckTyped(entity)
- ? this.TypeSystemServices.DuckType
- : entity.ReturnType;
- }
- private IType GetInferredType(IMember entity)
- {
- Debug.Assert(EntityType.Method != entity.EntityType);
- return IsDuckTyped(entity)
- ? this.TypeSystemServices.DuckType
- : entity.Type;
- }
- void ReplaceTypeInvocationByEval(IType type, MethodInvocationExpression node)
- {
- Node parent = node.ParentNode;
- parent.Replace(node, EvalForTypeInvocation(type, node));
- }
- private MethodInvocationExpression EvalForTypeInvocation(IType type, MethodInvocationExpression node)
- {
- 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);
- return 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
- {
- //EnsureRelatedNodeWasVisited(pair.First, setter);
- eval.Arguments.Add(
- CodeBuilder.CreateAssignment(
- pair.First.LexicalInfo,
- CodeBuilder.CreateMemberReference(
- instance.CloneNode(),
- property),
- pair.Second));
- }
- break;
- }
- }
- }
- void ProcessEventInvocation(IEvent ev, MethodInvocationExpression node)
- {
- NamedArgumentsNotAllowed(node);
- if (!EnsureInternalEventInvocation(ev, node)) return;
- IMethod method = ev.GetRaiseMethod();
- if (AssertParameters(node, method, node.Arguments))
- {
- node.Target = CodeBuilder.CreateMemberReference(
- ((MemberReferenceExpression)node.Target).Target,
- method);
- BindExpressionType(node, method.ReturnType);
- }
- }
- public bool EnsureInternalEventInvocation(IEvent ev, MethodInvocationExpression node)
- {
- if (ev.IsAbstract || ev.IsVirtual || ev.DeclaringType == CurrentType)
- return true;
- Error(CompilerErrorFactory.EventCanOnlyBeInvokedFromWithinDeclaringClass(node, ev));
- return false;
- }
- 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 = CreateInstanceInvocationFor(node);
- if (invocation.NamedArguments.Count == 0)
- {
- node.ParentNode.Replace(node, invocation);
- return;
- }
- ProcessNamedArgumentsForTypeInvocation(invocation);
- node.ParentNode.Replace(node, EvalForTypeInvocation(TypeSystemServices.ObjectType, invocation));
- }
- private void ProcessNamedArgumentsForTypeInvocation(MethodInvocationExpression invocation)
- {
- foreach (ExpressionPair pair in invocation.NamedArguments)
- {
- if (!ProcessNamedArgument(pair)) continue;
- NamedArgumentNotFound(TypeSystemServices.ObjectType, (ReferenceExpression)pair.First);
- }
- }
- private MethodInvocationExpression CreateInstanceInvocationFor(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));
- }
- invocation.NamedArguments = node.NamedArguments;
- return 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;
- }
- private 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)
- {
- BindNullableOperation(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;
- }
- bool BindNullableOperation(BinaryExpression node)
- {
- if (!IsNullableOperation(node))
- return false;
- if (BinaryOperatorType.ReferenceEquality == node.Operator)
- {
- node.Operator = BinaryOperatorType.Equality;
- return BindNullableComparison(node);
- }
- else if (BinaryOperatorType.ReferenceInequality == node.Operator)
- {
- node.Operator = BinaryOperatorType.Inequality;
- return BindNullableComparison(node);
- }
- IType lhs = GetExpressionType(node.Left);
- IType rhs = GetExpressionType(node.Right);
- bool lhsIsNullable = TypeSystemServices.IsNullable(lhs);
- bool rhsIsNullable = TypeSystemServices.IsNullable(rhs);
- if (BinaryOperatorType.Assign == node.Operator)
- {
- if (lhsIsNullable)
- {
- if (rhsIsNullable)
- return false;
- BindNullableInitializer(node, node.Right, lhs);
- return false;
- }
- }
- if (lhsIsNullable)
- {
- MemberReferenceExpression mre = new MemberReferenceExpression(node.Left, "Value");
- node.Replace(node.Left, mre);
- Visit(mre);
- mre.Annotate("nullableTarget", true);
- }
- if (rhsIsNullable)
- {
- MemberReferenceExpression mre = new MemberReferenceExpression(node.Right, "Value");
- node.Replace(node.Right, mre);
- Visit(mre);
- mre.Annotate("nullableTarget", true);
- }
- return false;
- }
- bool BindNullableComparison(BinaryExpression node)
- {
- if (!IsNullableOperation(node))
- return false;
- if (IsNull(node.Left) || IsNull(node.Right))
- {
- Expression nullable = IsNull(node.Left) ? node.Right : node.Left;
- Expression val = new MemberReferenceExpression(nullable, "HasValue");
- node.Replace(node.Left, val);
- Visit(val);
- Expression nil = new BoolLiteralExpression(false);
- node.Replace(node.Right, nil);
- Visit(nil);
- BindExpressionType(node, TypeSystemServices.BoolType);
- return true;
- }
- BinaryExpression valueCheck = new BinaryExpression(
- (node.Operator == BinaryOperatorType.Inequality)
- ? BinaryOperatorType.BitwiseOr
- : BinaryOperatorType.BitwiseAnd,
- new BinaryExpression(
- GetCorrespondingHasValueOperator(node.Operator),
- CreateNullableHasValueOrTrueExpression(node.Left),
- CreateNullableHasValueOrTrueExpression(node.Right)
- ),
- new BinaryExpression(
- node.Operator,
- CreateNullableGetValueOrDefaultExpression(node.Left),
- CreateNullableGetValueOrDefaultExpression(node.Right)
- )
- );
- node.ParentNode.Replace(node, valueCheck);
- Visit(valueCheck);
- return true;
- }
- private BinaryOperatorType GetCorrespondingHasValueOperator(BinaryOperatorType op)
- {
- if (BinaryOperatorType.Equality == op || BinaryOperatorType.Inequality == op)
- return op;
- //when there is at least one non-value operand then any other comparison
- //than equality/inequality is undefined/false (as in C#)
- return BinaryOperatorType.BitwiseAnd;
- }
- private IEnumerable<Expression> FindNullableExpressions(Expression exp)
- {
- if (exp.ContainsAnnotation("nullableTarget"))
- {
- yield return ((MemberReferenceExpression) exp).Target;
- }
- else
- {
- BinaryExpression bex = exp as BinaryExpression;
- if (null != bex)
- {
- foreach (Expression inner in FindNullableExpressions(bex.Left))
- yield return inner;
- foreach (Expression inner in FindNullableExpressions(bex.Right))
- yield return inner;
- }
- }
- }
- private Expression BuildNullableCoalescingConditional(Expression exp)
- {
- if (IsNull(exp)) return null;
- IEnumerator<Expression> enumerator = FindNullableExpressions(exp).GetEnumerator();
- Expression root = null;
- BinaryExpression and = null;
- Expression lookahead = null;
- while (enumerator.MoveNext())
- {
- Expression cur = enumerator.Current;
- lookahead = enumerator.MoveNext() ? enumerator.Current : null;
- if (null != and)
- {
- and.Right = new BinaryExpression(
- BinaryOperatorType.BitwiseAnd,
- and.Right,
- new BinaryExpression(
- BinaryOperatorType.BitwiseAnd,
- CreateNullableHasValueOrTrueExpression(cur),
- CreateNullableHasValueOrTrueExpression(lookahead)
- )
- );
- }
- else
- {
- if (null == lookahead)
- return CreateNullableHasValueOrTrueExpression(cur);
- root = and = new BinaryExpression(
- BinaryOperatorType.BitwiseAnd,
- CreateNullableHasValueOrTrueExpression(cur),
- CreateNullableHasValueOrTrueExpression(lookahead)
- );
- }
- }
- return root;
- }
- void BindNullableInitializer(Node node, Expression rhs, IType type)
- {
- Expression instantiation = CreateNullableInstantiation(rhs, type);
- node.Replace(rhs, instantiation);
- Visit(instantiation);
- Expression coalescing = BuildNullableCoalescingConditional(rhs);
- if (null != coalescing) //rhs contains at least one nullable
- {
- ConditionalExpression cond = new ConditionalExpression();
- cond.Condition = coalescing;
- cond.TrueValue = instantiation;
- cond.FalseValue = CreateNullableInstantiation(type);
- node.Replace(instantiation, cond);
- Visit(cond);
- }
- }
- private Expression CreateNullableInstantiation(IType type)
- {
- return CreateNullableInstantiation(null, type);
- }
- private Expression CreateNullableInstantiation(Expression val, IType type)
- {
- MethodInvocationExpression mie = new MethodInvocationExpression();
- GenericReferenceExpression gre = new GenericReferenceExpression();
- gre.Target = new MemberReferenceExpression(new ReferenceExpression("System"), "Nullable");
- gre.GenericArguments.Add(TypeReference.Lift(Nullable.GetUnderlyingType(((ExternalType) type).ActualType)));
- mie.Target = gre;
- if (null != val && !IsNull(val))
- mie.Arguments.Add(val);
- return mie;
- }
- private Expression CreateNullableHasValueOrTrueExpression(Expression target)
- {
- if (null == target || !TypeSystemServices.IsNullable(GetExpressionType(target)))
- return new BoolLiteralExpression(true);
- return new MemberReferenceExpression(target, "HasValue");
- }
- private Expression CreateNullableGetValueOrDefaultExpression(Expression target)
- {
- if (null == target || !TypeSystemServices.IsNullable(GetExpressionType(target)))
- return target;
- MethodInvocationExpression mie = new MethodInvocationExpression();
- mie.Target = new MemberReferenceExpression(target, "GetValueOrDefault");
- return mie;
- }
- void BindTypeTest(BinaryExpression node)
- {
- if (CheckIsNotValueType(node, node.Left) &&
- CheckIsaArgument(node.Right))
- {
- BindExpressionType(node, TypeSystemServices.BoolType);
- }
- else
- {
- Error(node);
- }
- }
- void BindReferenceEquality(BinaryExpression node)
- {
- if (BindNullableOperation(node))
- {
- return;
- }
- 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.InPlaceModulus:
- return BinaryOperatorType.Modulus;
- case BinaryOperatorType.InPlaceBitwiseAnd:
- return BinaryOperatorType.BitwiseAnd;
- case BinaryOperatorType.InPlaceBitwiseOr:
- return BinaryOperatorType.BitwiseOr;
- case BinaryOperatorType.InPlaceExclusiveOr:
- return BinaryOperatorType.ExclusiveOr;
- 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)
- {
- BindNullableOperation(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).Select(IsPublicFieldPropertyEvent);
- 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)
- {
- if (!ProcessNamedArgument(arg)) continue;
- ResolveNamedArgument(type, (ReferenceExpression)arg.First, arg.Second);
- }
- }
- private bool ProcessNamedArgument(ExpressionPair arg)
- {
- Visit(arg.Second);
- if (NodeType.ReferenceExpression != arg.First.NodeType)
- {
- Error(arg.First, CompilerErrorFactory.NamedParameterMustBeIdentifier(arg));
- return false;
- }
- return true;
- }
- void ResolveNamedArgument(IType type, ReferenceExpression name, Expression value)
- {
- IMember member = ResolvePublicFieldPropertyEvent(name, type, name.Name);
- if (null == member)
- {
- NamedArgumentNotFound(type, name);
- return;
- }
- EnsureRelatedNodeWasVisited(name, member);
- 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.IsNullable(expectedType) && EntityType.Null == actualType.EntityType)
- {
- return true;
- }
- 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<args.Count; ++i)
- {
- IType expressionType = GetExpressionType(args[i]);
- IType parameterType = parameters[i].Type;
- if (!IsAssignableFrom(parameterType, expressionType) &&
- !(IsNumber(expressionType) && IsNumber(parameterType))
- && TypeSystemServices.FindImplicitConversionOperator(expressionType,parameterType) == null)
- {
- return false;
- }
- }
- return true;
- }
- bool AssertParameterTypes(ICallableType method, ExpressionCollection args, int count, bool reportErrors)
- {
- IParameter[] parameters = method.GetSignature().Parameters;
- for (int i=0; i<count; ++i)
- {
- IParameter param = parameters[i];
- IType parameterType = param.Type;
- IType argumentType = GetExpressionType(args[i]);
- if (param.IsByRef)
- {
- if (!(args[i] is ReferenceExpression
- || args[i] is SlicingExpression))
- {
- if (reportErrors) Error(CompilerErrorFactory.RefArgTakesLValue(args[i]));
- return false;
- }
- if (!_callableResolution.IsValidByRefArg(param, parameterType, argumentType, args[i]))
- {
- return false;
- }
- }
- else
- {
- if (!TypeSystemServices.AreTypesRelated(parameterType, argumentType))
- {
- return false;
- }
- }
- }
- return true;
- }
- bool AssertParameters(Node sourceNode, IMethod method, ExpressionCollection args)
- {
- return AssertParameters(sourceNode, method, method.CallableType, args);
- }
- bool AcceptVarArgs(ICallableType method)
- {
- return method.GetSignature().AcceptVarArgs;
- }
- bool AssertParameters(Node sourceNode, IEntity sourceEntity, ICallableType method, ExpressionCollection args)
- {
- if (CheckParameters(method, args, true)) return true;
- Error(CompilerErrorFactory.MethodSignature(sourceNode, sourceEntity.ToString(), GetSignature(args)));
- return false;
- }
- protected virtual bool CheckParameters(ICallableType method, ExpressionCollection args, bool reportErrors)
- {
- return AcceptVarArgs(method)
- ? CheckVarArgsParameters(method, args)
- : CheckExactArgsParameters(method, args, reportErrors);
- }
- protected bool CheckVarArgsParameters(ICallableType method, ExpressionCollection args)
- {
- return _callableResolution.IsValidVargsInvocation(method.GetSignature().Parameters, args);
- }
- protected bool CheckExactArgsParameters(ICallableType method, ExpressionCollection args, bool reportErrors)
- {
- if (method.GetSignature().Parameters.Length != args.Count) return false;
- return AssertParameterTypes(method, args, args.Count, reportErrors);
- }
- bool IsRuntimeIterator(IType type)
- {
- return TypeSystemServices.IsSystemObject(type)
- || IsTextReader(type);
- }
- bool IsTextReader(IType type)
- {
- return IsAssignableFrom(typeof(TextReader), type);
- }
- bool AssertTargetContext(Expression targetContext, IMember member)
- {
- if (member.IsStatic) return true;
- if (NodeType.MemberReferenceExpression != targetContext.NodeType) return true;
- Expression targetReference = ((MemberReferenceExpression)targetContext).Target;
- IEntity entity = targetReference.Entity;
- if ((null != entity && EntityType.Type == entity.EntityType)
- || (NodeType.SelfLiteralExpression == targetReference.NodeType
- && _currentMethod.IsStatic))
- {
- Error(CompilerErrorFactory.InstanceRequired(targetContext, member.DeclaringType.ToString(), member.Name));
- return false;
- }
- return true;
- }
- static bool IsAssignableFrom(IType expectedType, IType actualType)
- {
- return expectedType.IsAssignableFrom(actualType);
- }
- bool IsAssignableFrom(Type expectedType, IType actualType)
- {
- return TypeSystemServices.Map(expectedType).IsAssignableFrom(actualType);
- }
- bool IsNumber(IType type)
- {
- return TypeSystemServices.IsNumber(type);
- }
- bool IsPrimitiveNumber(IType type)
- {
- return TypeSystemServices.IsPrimitiveNumber(type);
- }
- bool IsPrimitiveNumber(Expression expression)
- {
- return IsPrimitiveNumber(GetExpressionType(expression));
- }
- IConstructor GetCorrectConstructor(Node sourceNode, IType type, ExpressionCollection arguments)
- {
- IConstructor[] constructors = type.GetConstructors();
- if (null != constructors && constructors.Length > 0)
- {
- return (IConstructor)GetCorrectCallableReference(sourceNode, arguments, constructors);
- }
- else
- {
- if (!TypeSystemServices.IsError(type))
- {
- if (null == (type as IGenericParameter))
- {
- Error(CompilerErrorFactory.NoApropriateConstructorFound(sourceNode, type.ToString(), GetSignature(arguments)));
- }
- else
- {
- Error(CompilerErrorFactory.CannotCreateAnInstanceOfGenericParameterWithoutDefaultConstructorConstraint(sourceNode, type.ToString()));
- }
- }
- }
- return null;
- }
- IEntity GetCorrectCallableReference(Node sourceNode, ExpressionCollection args, IEntity[] candidates)
- {
- // BOO-844: Ensure all candidates were visited (to make property setters have correct signature)
- foreach (IEntity candidate in candidates)
- {
- EnsureRelatedNodeWasVisited(sourceNode, candidate);
- }
- IEntity found = _callableResolution.ResolveCallableReference(args, candidates);
- if (null == found) EmitCallableResolutionError(sourceNode, candidates, args);
- return found;
- }
- private void EmitCallableResolutionError(Node sourceNode, IEntity[] candidates, ExpressionCollection args)
- {
- if (_callableResolution.ValidCandidates.Count > 1)
- {
- Error(CompilerErrorFactory.AmbiguousReference(sourceNode, candidates[0].Name, _callableResolution.ValidCandidates));
- }
- else
- {
- IEntity candidate = candidates[0];
- IConstructor constructor = candidate as IConstructor;
- if (null != constructor)
- {
- Error(CompilerErrorFactory.NoApropriateConstructorFound(sourceNode, constructor.DeclaringType.ToString(), GetSignature(args)));
- }
- else
- {
- Error(CompilerErrorFactory.NoApropriateOverloadFound(sourceNode, GetSignature(args), candidate.FullName));
- }
- }
- }
- override protected void EnsureRelatedNodeWasVisited(Node sourceNode, IEntity entity)
- {
- IInternalEntity internalInfo = entity as IInternalEntity;
- if (null == internalInfo)
- {
- ITypedEntity typedEntity = entity as ITypedEntity;
- if (null == typedEntity) return;
- internalInfo = typedEntity.Type as IInternalEntity;
- if (null == internalInfo) return;
- }
- Node node = internalInfo.Node;
- //member has been used so remove private member unused annotation
- TypeMember member = node as TypeMember;
- if (null != member
- && member.IsPrivate
- && member.ContainsAnnotation("PrivateMemberNeverUsed"))
- {
- node.RemoveAnnotation("PrivateMemberNeverUsed");
- }
- switch (node.NodeType)
- {
- case NodeType.Property:
- case NodeType.Field:
- {
- IMember memberEntity = (IMember)entity;
- if (EntityType.Property == entity.EntityType
- || TypeSystemServices.IsUnknown(memberEntity.Type))
- {
- VisitMemberForTypeResolution(node);
- AssertTypeIsKnown(sourceNode, memberEntity, memberEntity.Type);
- }
- break;
- }
- case NodeType.Method:
- {
- IMethod methodEntity = (IMethod)entity;
- if (TypeSystemServices.IsUnknown(methodEntity.ReturnType))
- {
- // try to preprocess the method to resolve its return type
- Method method = (Method)node;
- PreProcessMethod(method);
- if (TypeSystemServices.IsUnknown(methodEntity.ReturnType))
- {
- // still unknown?
- VisitMemberForTypeResolution(node);
- AssertTypeIsKnown(sourceNode, methodEntity, methodEntity.ReturnType);
- }
- }
- break;
- }
- case NodeType.ClassDefinition:
- case NodeType.StructDefinition:
- case NodeType.InterfaceDefinition:
- {
- if (WasVisited(node)) break;
- VisitInParentNamespace(node);
- //visit dependent attributes such as EnumeratorItemType
- //foreach (Attribute att in ((TypeDefinition)node).Attributes)
- {
- //VisitMemberForTypeResolution(att);
- }
- break;
- }
- }
- }
- private void VisitInParentNamespace(Node node)
- {
- INamespace saved = NameResolutionService.CurrentNamespace;
- try
- {
- NameResolutionService.EnterNamespace((INamespace)node.ParentNode.Entity);
- Visit(node);
- }
- finally
- {
- NameResolutionService.Restore(saved);
- }
- }
- private void AssertTypeIsKnown(Node sourceNode, IEntity sourceEntity, IType type)
- {
- if (TypeSystemServices.IsUnknown(type))
- {
- Error(
- CompilerErrorFactory.UnresolvedDependency(
- sourceNode,
- CurrentMember.FullName,
- sourceEntity.FullName));
- }
- }
- void VisitMemberForTypeResolution(Node node)
- {
- if (WasVisited(node)) return;
- _context.TraceVerbose("Info {0} needs resolving.", node.Entity.Name);
- INamespace saved = NameResolutionService.CurrentNamespace;
- try
- {
- Visit(node);
- }
- finally
- {
- NameResolutionService.Restore(saved);
- }
- }
- bool ResolveOperator(UnaryExpression node)
- {
- MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo);
- mie.Arguments.Add(node.Operand.CloneNode());
- string operatorName = AstUtil.GetMethodNameForOperator(node.Operator);
- IType operand = GetExpressionType(node.Operand);
- if (ResolveOperator(node, operand, operatorName, mie))
- {
- return true;
- }
- return ResolveOperator(node, TypeSystemServices.RuntimeServicesType, operatorName, mie);
- }
- bool ResolveOperator(BinaryExpression node)
- {
- MethodInvocationExpression mie = new MethodInvocationExpression(node.LexicalInfo);
- mie.Arguments.Add(node.Left.CloneNode());
- mie.Arguments.Add(node.Right.CloneNode());
- string operatorName = AstUtil.GetMethodNameForOperator(node.Operator);
- IType lhs = GetExpressionType(node.Left);
- if (ResolveOperator(node, lhs, operatorName, mie))
- {
- return true;
- }
- IType rhs = GetExpressionType(node.Right);
- if (ResolveOperator(node, rhs, operatorName, mie))
- {
- return true;
- }
- return ResolveRuntimeOperator(node, operatorName, mie);
- }
- protected virtual bool ResolveRuntimeOperator(BinaryExpression node, string operatorName, MethodInvocationExpression mie)
- {
- return ResolveOperator(node, TypeSystemServices.RuntimeServicesType, operatorName, mie);
- }
- IMethod ResolveAmbiguousOperator(IEntity[] entities, ExpressionCollection args)
- {
- foreach (IEntity entity in entities)
- {
- IMethod method = entity as IMethod;
- if (null != method)
- {
- if (HasOperatorSignature(method, args))
- {
- return method;
- }
- }
- }
- return null;
- }
- bool HasOperatorSignature(IMethod method, ExpressionCollection args)
- {
- return method.IsStatic &&
- (args.Count == method.GetParameters().Length) &&
- CheckParameterTypesStrictly(method, args);
- }
- IMethod FindOperator(IType type, string operatorName, ExpressionCollection args)
- {
- IEntity entity = NameResolutionService.Resolve(type, operatorName, EntityType.Method);
- if (null != entity)
- {
- IMethod method = ResolveOperatorEntity(entity, args);
- if (null != method) return method;
- }
- entity = NameResolutionService.ResolveExtension(type, operatorName);
- if (null != entity)
- {
- return ResolveOperatorEntity(entity, args);
- }
- return null;
- }
- private IMethod ResolveOperatorEntity(IEntity op, ExpressionCollection args)
- {
- if (EntityType.Ambiguous == op.EntityType)
- {
- return ResolveAmbiguousOperator(((Ambiguous)op).Entities, args);
- }
- if (EntityType.Method == op.EntityType)
- {
- IMethod candidate = (IMethod)op;
- if (HasOperatorSignature(candidate, args))
- {
- return candidate;
- }
- }
- return null;
- }
- bool ResolveOperator(Expression node, IType type, string operatorName, MethodInvocationExpression mie)
- {
- IMethod entity = FindOperator(type, operatorName, mie.Arguments);
- if (null == entity) return false;
- EnsureRelatedNodeWasVisited(node, entity);
- mie.Target = new ReferenceExpression(entity.FullName);
- IMethod operatorMethod = entity;
- BindExpressionType(mie, operatorMethod.ReturnType);
- BindExpressionType(mie.Target, operatorMethod.Type);
- Bind(mie.Target, entity);
- node.ParentNode.Replace(node, mie);
- return true;
- }
- Expression AssertBoolContext(Expression expression)
- {
- IType type = GetExpressionType(expression);
- if (type == TypeSystemServices.BoolType) return expression;
- if (IsNumber(type)) return expression;
- if (type.IsEnum) return expression;
- // nullable types can be used in bool context
- if (TypeSystemServices.IsNullable(type))
- {
- MemberReferenceExpression mre = new MemberReferenceExpression(expression, "HasValue");
- Visit(mre);
- return mre;
- }
- IMethod method = TypeSystemServices.FindImplicitConversionOperator(type, TypeSystemServices.BoolType);
- if (null != method) return CodeBuilder.CreateMethodInvocation(method, expression);
- // reference types can be used in bool context
- if (!type.IsValueType) return expression;
- Error(CompilerErrorFactory.BoolExpressionRequired(expression, type.ToString()));
- return expression;
- }
- ReferenceExpression CreateTempLocal(LexicalInfo li, IType type)
- {
- InternalLocal local = DeclareTempLocal(type);
- ReferenceExpression reference = new ReferenceExpression(li, local.Name);
- reference.Entity = local;
- reference.ExpressionType = type;
- return reference;
- }
- protected InternalLocal DeclareTempLocal(IType localType)
- {
- return CodeBuilder.DeclareTempLocal(_currentMethod.Method, localType);
- }
- IEntity DeclareLocal(Node sourceNode, string name, IType localType)
- {
- return DeclareLocal(sourceNode, name, localType, false);
- }
- virtual protected IEntity DeclareLocal(Node sourceNode, string name, IType localType, bool privateScope)
- {
- Local local = new Local(name, privateScope);
- local.LexicalInfo = sourceNode.LexicalInfo;
- InternalLocal entity = new InternalLocal(local, localType);
- local.Entity = entity;
- _currentMethod.Method.Locals.Add(local);
- return entity;
- }
- protected IType CurrentType
- {
- get
- {
- return _currentMethod.DeclaringType;
- }
- }
- void PushMember(TypeMember member)
- {
- _memberStack.Push(member);
- }
- TypeMember CurrentMember
- {
- get
- {
- return (TypeMember)_memberStack.Peek();
- }
- }
- void PopMember()
- {
- _memberStack.Pop();
- }
- void PushMethodInfo(InternalMethod tag)
- {
- _methodStack.Push(_currentMethod);
- _currentMethod = tag;
- }
- void PopMethodInfo()
- {
- _currentMethod = (InternalMethod)_methodStack.Pop();
- }
- void AssertHasSideEffect(Expression expression)
- {
- if (!HasSideEffect(expression) && !TypeSystemServices.IsError(expression))
- {
- Error(CompilerErrorFactory.ExpressionMustBeExecutedForItsSideEffects(expression));
- }
- }
- protected virtual bool HasSideEffect(Expression node)
- {
- return
- node.NodeType == NodeType.MethodInvocationExpression ||
- AstUtil.IsAssignment(node) ||
- AstUtil.IsIncDec(node);
- }
- bool AssertCanCreateInstance(Node sourceNode, IType type)
- {
- if (type.IsInterface)
- {
- Error(CompilerErrorFactory.CantCreateInstanceOfInterface(sourceNode, type.ToString()));
- return false;
- }
- if (type.IsEnum)
- {
- Error(CompilerErrorFactory.CantCreateInstanceOfEnum(sourceNode, type.ToString()));
- return false;
- }
- if (type.IsAbstract)
- {
- Error(CompilerErrorFactory.CantCreateInstanceOfAbstractType(sourceNode, type.ToString()));
- return false;
- }
- if (!(type is GenericConstructedType)
- &&
- ((type.GenericInfo != null
- && type.GenericInfo.GenericParameters.Length > 0)
- || (type.ConstructedInfo != null
- && !type.ConstructedInfo.FullyConstructed))
- )
- {
- Error(CompilerErrorFactory.GenericTypesMustBeConstructedToBeInstantiated(sourceNode));
- return false;
- }
- return true;
- }
- bool AssertDeclarationName(Declaration d)
- {
- if (AssertIdentifierName(d, d.Name))
- {
- return AssertUniqueLocal(d);
- }
- return false;
- }
- bool AssertUniqueLocal(Declaration d)
- {
- if (null == _currentMethod.ResolveLocal(d.Name) &&
- null == _currentMethod.ResolveParameter(d.Name))
- {
- return true;
- }
- Error(CompilerErrorFactory.LocalAlreadyExists(d, d.Name));
- return false;
- }
- void GetDeclarationType(IType defaultDeclarationType, Declaration d)
- {
- if (null != d.Type)
- {
- Visit(d.Type);
- AssertTypeCompatibility(d, GetType(d.Type), defaultDeclarationType);
- }
- else
- {
- d.Type = CodeBuilder.CreateTypeReference(defaultDeclarationType);
- }
- }
- void DeclareLocal(Declaration d, bool privateScope)
- {
- if (AssertIdentifierName(d, d.Name))
- {
- d.Entity = DeclareLocal(d, d.Name, GetType(d.Type), privateScope);
- }
- }
- protected IType GetEnumeratorItemType(IType iteratorType)
- {
- return TypeSystemServices.GetEnumeratorItemType(iteratorType);
- }
- protected void ProcessDeclarationsForIterator(DeclarationCollection declarations, IType iteratorType)
- {
- IType defaultDeclType = GetEnumeratorItemType(iteratorType);
- if (declarations.Count > 1)
- {
- // will enumerate (unpack) each item
- defaultDeclType = GetEnumeratorItemType(defaultDeclType);
- }
- foreach (Declaration d in declarations)
- {
- ProcessDeclarationForIterator(d, defaultDeclType);
- }
- }
- protected void ProcessDeclarationForIterator(Declaration d, IType defaultDeclType)
- {
- GetDeclarationType(defaultDeclType, d);
- DeclareLocal(d, true);
- }
- protected virtual bool AssertLValue(Node node)
- {
- IEntity entity = node.Entity;
- if (null != entity) return AssertLValue(node, entity);
- if (IsArraySlicing(node)) return true;
- Error(CompilerErrorFactory.LValueExpected(node));
- return false;
- }
- protected virtual bool AssertLValue(Node node, IEntity entity)
- {
- if (null != entity)
- {
- switch (entity.EntityType)
- {
- case EntityType.Parameter:
- case EntityType.Local:
- {
- return true;
- }
- case EntityType.Property:
- {
- if (null == ((IProperty)entity).GetSetMethod())
- {
- Error(CompilerErrorFactory.PropertyIsReadOnly(AstUtil.GetMemberAnchor(node), entity.FullName));
- return false;
- }
- return true;
- }
- case EntityType.Field:
- {
- IField fld = (IField)entity;
- if (TypeSystemServices.IsReadOnlyField(fld)
- && !(EntityType.Constructor == _currentMethod.EntityType
- && _currentMethod.DeclaringType == fld.DeclaringType
- && fld.IsStatic == _currentMethod.IsStatic))
- {
- Error(CompilerErrorFactory.FieldIsReadonly(AstUtil.GetMemberAnchor(node), entity.FullName));
- return false;
- }
- return true;
- }
- }
- }
- Error(CompilerErrorFactory.LValueExpected(node));
- return false;
- }
- public static bool IsArraySlicing(Node node)
- {
- if (node.NodeType != NodeType.SlicingExpression) return false;
- IType type = ((SlicingExpression)node).Target.ExpressionType;
- return null != type && type.IsArray;
- }
- bool IsStandaloneReference(Node node)
- {
- Node parent = node.ParentNode;
- if (parent is GenericReferenceExpression)
- {
- parent = parent.ParentNode;
- }
- return parent.NodeType != NodeType.MemberReferenceExpression;
- }
- string GetSignature(IEnumerable args)
- {
- StringBuilder sb = new StringBuilder("(");
- foreach (Expression arg in args)
- {
- if (sb.Length > 1)
- {
- sb.Append(", ");
- }
- if (AstUtil.IsExplodeExpression(arg))
- {
- sb.Append('*');
- }
- sb.Append(GetExpressionType(arg));
- }
- sb.Append(")");
- return sb.ToString();
- }
- void InvalidOperatorForType(UnaryExpression node)
- {
- Error(node, CompilerErrorFactory.InvalidOperatorForType(node,
- GetUnaryOperatorText(node.Operator),
- GetExpressionType(node.Operand).ToString()));
- }
- void InvalidOperatorForTypes(BinaryExpression node)
- {
- Error(node, CompilerErrorFactory.InvalidOperatorForTypes(node,
- GetBinaryOperatorText(node.Operator),
- GetExpressionType(node.Left).ToString(),
- GetExpressionType(node.Right).ToString()));
- }
- void TraceReturnType(Method method, IMethod tag)
- {
- _context.TraceInfo("{0}: return type for method {1} bound to {2}", method.LexicalInfo, method.Name, tag.ReturnType);
- }
- #region Method bindings cache
- IMethod _RuntimeServices_Len;
- IMethod RuntimeServices_Len
- {
- get
- {
- if (null == _RuntimeServices_Len)
- {
- _RuntimeServices_Len = ResolveMethod(TypeSystemServices.RuntimeServicesType, "Len");
- }
- return _RuntimeServices_Len;
- }
- }
- IMethod _RuntimeServices_Mid;
- IMethod RuntimeServices_Mid
- {
- get
- {
- if (null == _RuntimeServices_Mid)
- {
- _RuntimeServices_Mid = ResolveMethod(TypeSystemServices.RuntimeServicesType, "Mid");
- }
- return _RuntimeServices_Mid;
- }
- }
- IMethod _RuntimeServices_NormalizeStringIndex;
- IMethod RuntimeServices_NormalizeStringIndex
- {
- get
- {
- if (null == _RuntimeServices_NormalizeStringIndex)
- {
- _RuntimeServices_NormalizeStringIndex = ResolveMethod(TypeSystemServices.RuntimeServicesType, "NormalizeStringIndex");
- }
- return _RuntimeServices_NormalizeStringIndex;
- }
- }
- IMethod _RuntimeServices_AddArrays;
- IMethod RuntimeServices_AddArrays
- {
- get
- {
- if (null == _RuntimeServices_AddArrays)
- {
- _RuntimeServices_AddArrays = ResolveMethod(TypeSystemServices.RuntimeServicesType, "AddArrays");
- }
- return _RuntimeServices_AddArrays;
- }
- }
- IMethod _RuntimeServices_GetRange1;
- IMethod RuntimeServices_GetRange1
- {
- get
- {
- if (null == _RuntimeServices_GetRange1)
- {
- _RuntimeServices_GetRange1 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetRange1");
- }
- return _RuntimeServices_GetRange1;
- }
- }
- IMethod _RuntimeServices_GetRange2;
- IMethod RuntimeServices_GetRange2
- {
- get
- {
- if (null == _RuntimeServices_GetRange2)
- {
- _RuntimeServices_GetRange2 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetRange2");
- }
- return _RuntimeServices_GetRange2;
- }
- }
- IMethod _RuntimeServices_GetMultiDimensionalRange1;
- IMethod RuntimeServices_GetMultiDimensionalRange1
- {
- get
- {
- if (null == _RuntimeServices_GetMultiDimensionalRange1)
- {
- _RuntimeServices_GetMultiDimensionalRange1 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetMultiDimensionalRange1");
- }
- return _RuntimeServices_GetMultiDimensionalRange1;
- }
- }
- IMethod _RuntimeServices_SetMultiDimensionalRange1;
- IMethod RuntimeServices_SetMultiDimensionalRange1
- {
- get
- {
- if (null == _RuntimeServices_SetMultiDimensionalRange1)
- {
- _RuntimeServices_SetMultiDimensionalRange1 = ResolveMethod(TypeSystemServices.RuntimeServicesType, "SetMultiDimensionalRange1");
- }
- return _RuntimeServices_SetMultiDimensionalRange1;
- }
- }
- IMethod _RuntimeServices_GetEnumerable;
- IMethod RuntimeServices_GetEnumerable
- {
- get
- {
- if (null == _RuntimeServices_GetEnumerable)
- {
- _RuntimeServices_GetEnumerable = ResolveMethod(TypeSystemServices.RuntimeServicesType, "GetEnumerable");
- }
- return _RuntimeServices_GetEnumerable;
- }
- }
- IMethod _RuntimeServices_EqualityOperator;
- IMethod RuntimeServices_EqualityOperator
- {
- get
- {
- if (null == _RuntimeServices_EqualityOperator)
- {
- _RuntimeServices_EqualityOperator = TypeSystemServices.Map(Types.RuntimeServices.GetMethod("EqualityOperator", new Type[] { Types.Object, Types.Object }));
- }
- return _RuntimeServices_EqualityOperator;
- }
- }
- IMethod _Array_get_Length;
- IMethod Array_get_Length
- {
- get
- {
- if (null == _Array_get_Length)
- {
- _Array_get_Length = ResolveProperty(TypeSystemServices.ArrayType, "Length").GetGetMethod();
- }
- return _Array_get_Length;
- }
- }
- IMethod _Array_GetLength;
- IMethod Array_GetLength
- {
- get
- {
- if (null == _Array_GetLength)
- {
- _Array_GetLength = ResolveMethod(TypeSystemServices.ArrayType, "GetLength");
- }
- return _Array_GetLength;
- }
- }
- IMethod _String_get_Length;
- IMethod String_get_Length
- {
- get
- {
- if (null == _String_get_Length)
- {
- _String_get_Length = ResolveProperty(TypeSystemServices.StringType, "Length").GetGetMethod();
- }
- return _String_get_Length;
- }
- }
- IMethod _String_Substring_Int;
- IMethod String_Substring_Int
- {
- get
- {
- if (null == _String_Substring_Int)
- {
- _String_Substring_Int = TypeSystemServices.Map(Types.String.GetMethod("Substring", new Type[] { Types.Int }));
- }
- return _String_Substring_Int;
- }
- }
- IMethod _ICollection_get_Count;
- IMethod ICollection_get_Count
- {
- get
- {
- if (null == _ICollection_get_Count)
- {
- _ICollection_get_Count = ResolveProperty(TypeSystemServices.ICollectionType, "Count").GetGetMethod();
- }
- return _ICollection_get_Count;
- }
- }
- IMethod _List_GetRange1;
- IMethod List_GetRange1
- {
- get
- {
- if (null == _List_GetRange1)
- {
- _List_GetRange1 = TypeSystemServices.Map(Types.List.GetMethod("GetRange", new Type[] { typeof(int) }));
- }
- return _List_GetRange1;
- }
- }
- IMethod _List_GetRange2;
- IMethod List_GetRange2
- {
- get
- {
- if (null == _List_GetRange2)
- {
- _List_GetRange2 = TypeSystemServices.Map(Types.List.GetMethod("GetRange", new Type[] { typeof(int), typeof(int) }));
- }
- return _List_GetRange2;
- }
- }
- IMethod _ICallable_Call;
- IMethod ICallable_Call
- {
- get
- {
- if (null == _ICallable_Call)
- {
- _ICallable_Call = ResolveMethod(TypeSystemServices.ICallableType, "Call");
- }
- return _ICallable_Call;
- }
- }
- IMethod _Activator_CreateInstance;
- IMethod Activator_CreateInstance
- {
- get
- {
- if (null == _Activator_CreateInstance)
- {
- _Activator_CreateInstance = TypeSystemServices.Map(typeof(Activator).GetMethod("CreateInstance", new Type[] { Types.Type, Types.ObjectArray }));
- }
- return _Activator_CreateInstance;
- }
- }
- IConstructor _Exception_StringConstructor;
- IConstructor Exception_StringConstructor
- {
- get
- {
- if (null == _Exception_StringConstructor)
- {
- _Exception_StringConstructor = TypeSystemServices.GetStringExceptionConstructor();
- }
- return _Exception_StringConstructor;
- }
- }
- IMethod _TextReaderEnumerator_lines;
- IMethod TextReaderEnumerator_lines
- {
- get
- {
- if (null == _TextReaderEnumerator_lines)
- {
- _TextReaderEnumerator_lines = TypeSystemServices.Map(typeof(TextReaderEnumerator).GetMethod("lines"));
- }
- return _TextReaderEnumerator_lines;
- }
- }
- public bool OptimizeNullComparisons
- {
- get { return _optimizeNullComparisons; }
- set { _optimizeNullComparisons = value; }
- }
- #endregion
- }
- }