Example #1
0
        private Expression ProcessOpenParenExpressionNode(BinaryExpressionNode node) {
            bool isDelegateInvoke = false;
            Expression leftExpression = BuildExpression(node.LeftChild);

            if (leftExpression is LocalExpression) {
                Debug.Assert(leftExpression.EvaluatedType.Type == SymbolType.Delegate);

                // Handle the implicit delegate invoke scenario by turning the expression
                // into an explicit call into the delegate's Invoke method

                MemberSymbol invokeMethodSymbol = leftExpression.EvaluatedType.GetMember("Invoke");
                Debug.Assert(invokeMethodSymbol != null);

                leftExpression = new MemberExpression(leftExpression, invokeMethodSymbol);
                isDelegateInvoke = true;
            }

            if (leftExpression.Type != ExpressionType.Member) {
                // A method call was evaluated into a non-member expression as part of building
                // the left node. For example, Nullable<T>.GetValueOrDefault() becomes a logical or expression.

                return leftExpression;
            }

            MemberExpression memberExpression = (MemberExpression)leftExpression;

            ExpressionListNode argNodes = null;
            List<Expression> args = null;
            if (node.RightChild != null) {
                Debug.Assert(node.RightChild is ExpressionListNode);

                argNodes = (ExpressionListNode)node.RightChild;
                args = BuildExpressionList(argNodes);
            }

            MethodExpression methodExpression = null;

            if (memberExpression.Member.Type != SymbolType.Method) {
                // A non-method member is being used in a method call; the member must be
                // a delegate...
                Debug.Assert(memberExpression.EvaluatedType.Type == SymbolType.Delegate);
                Expression instanceExpression = TransformMemberExpression(memberExpression);

                MethodSymbol invokeMethod =
                    (MethodSymbol)memberExpression.EvaluatedType.GetMember("Invoke");
                Debug.Assert(invokeMethod != null);

                methodExpression = new MethodExpression(instanceExpression, invokeMethod);
                isDelegateInvoke = true;
            }
            else {
                // The member being accessed is a method...

                // REVIEW: Uggh... this has become too complex over time with all the transformations
                //         added over time. Refactoring needed...

                MethodSymbol method = (MethodSymbol)memberExpression.Member;
                TypeSymbol objectType = _symbolSet.ResolveIntrinsicType(IntrinsicType.Object);
                TypeSymbol typeType = _symbolSet.ResolveIntrinsicType(IntrinsicType.Type);
                TypeSymbol dictionaryType = _symbolSet.ResolveIntrinsicType(IntrinsicType.Dictionary);
                TypeSymbol genericDictionaryType = _symbolSet.ResolveIntrinsicType(IntrinsicType.GenericDictionary);
                TypeSymbol numberType = _symbolSet.ResolveIntrinsicType(IntrinsicType.Number);
                TypeSymbol stringType = _symbolSet.ResolveIntrinsicType(IntrinsicType.String);
                TypeSymbol scriptType = _symbolSet.ResolveIntrinsicType(IntrinsicType.Script);
                TypeSymbol argsType = _symbolSet.ResolveIntrinsicType(IntrinsicType.Arguments);

                if ((method.Parent == objectType) &&
                    method.Name.Equals("GetType", StringComparison.Ordinal)) {
                    // Since we can't extend object's prototype, we need to transform the
                    // natural c# syntax into a static method.
                    // Object.GetType instance method becomes Type.GetInstanceType static method

                    TypeSymbol typeSymbol = typeType;

                    method = (MethodSymbol)typeSymbol.GetMember("GetInstanceType");
                    Debug.Assert(method != null);

                    methodExpression = new MethodExpression(new TypeExpression(typeSymbol, SymbolFilter.Public | SymbolFilter.StaticMembers),
                                                            method);
                    methodExpression.AddParameterValue(memberExpression.ObjectReference);
                    return methodExpression;
                }
                else if ((method.Parent == objectType) &&
                         (method.Name.Equals("ToString", StringComparison.Ordinal) ||
                          method.Name.Equals("ToLocaleString", StringComparison.Ordinal)) &&
                         (memberExpression.ObjectReference.EvaluatedType == stringType)) {
                    // No-op ToString calls on strings (this happens when performing a ToString
                    // on a named enum value.
                    return memberExpression.ObjectReference;
                }
                else if ((method.Parent == objectType) &&
                         (method.Name.Equals("ToString", StringComparison.Ordinal) ||
                          method.Name.Equals("ToLocaleString", StringComparison.Ordinal)) &&
                         (memberExpression.ObjectReference.EvaluatedType is EnumerationSymbol)) {
                    EnumerationSymbol enumSymbol = (EnumerationSymbol)memberExpression.ObjectReference.EvaluatedType;

                    if (enumSymbol.UseNamedValues) {
                        // If the enum value is a named enum, then it is already a string.
                        return memberExpression.ObjectReference;
                    }

                    return new MethodExpression(memberExpression.ObjectReference, method);
                }
                else if (((method.Parent == dictionaryType) || (method.Parent == genericDictionaryType)) &&
                         method.Name.Equals("ContainsKey", StringComparison.Ordinal)) {
                    // Switch the instance ContainsKey method on Dictionary to
                    // calls to the static KeyExists method.
                    Debug.Assert(args.Count == 1);

                    MethodSymbol keyExistsMethod = (MethodSymbol)dictionaryType.GetMember("KeyExists");
                    Debug.Assert(keyExistsMethod != null);

                    methodExpression = new MethodExpression(new TypeExpression(dictionaryType, SymbolFilter.Public | SymbolFilter.StaticMembers),
                                                            keyExistsMethod);
                    methodExpression.AddParameterValue(memberExpression.ObjectReference);
                    methodExpression.AddParameterValue(args[0]);

                    return methodExpression;
                }
                else if (((method.Parent == dictionaryType) || (method.Parent == genericDictionaryType)) &&
                         method.Name.Equals("Remove", StringComparison.Ordinal)) {
                    // Switch the instance Remove method on Dictionary to
                    // calls to the static DeleteKey method.
                    Debug.Assert(args.Count == 1);

                    return new LateBoundExpression(memberExpression.ObjectReference,
                                                   args[0], LateBoundOperation.DeleteField,
                                                   objectType);
                }
                else if (((method.Parent == dictionaryType) || (method.Parent == genericDictionaryType)) &&
                         method.Name.Equals("Clear")) {
                    // Switch the instance Clear method on Dictionary to
                    // calls to the static ClearKeys method.
                    MethodSymbol clearKeysMethod = (MethodSymbol)dictionaryType.GetMember("ClearKeys");
                    Debug.Assert(clearKeysMethod != null);

                    methodExpression = new MethodExpression(new TypeExpression(dictionaryType, SymbolFilter.Public | SymbolFilter.StaticMembers),
                                                            clearKeysMethod);
                    methodExpression.AddParameterValue(memberExpression.ObjectReference);
                    return methodExpression;
                }
                else if (((method.Parent == dictionaryType) || (((TypeSymbol)method.Parent).GenericType == genericDictionaryType)) &&
                         ((method.Visibility & MemberVisibility.Static) != 0) &&
                         method.Name.Equals("GetDictionary", StringComparison.Ordinal)) {
                    // Dictionary.GetDictionary is a no-op method; we're just interested
                    // in the object being passed in.
                    // However we'll re-evaluate the argument to be of dictionary type
                    // so that subsequent use of this expression sees it as a dictionary.
                    Debug.Assert(args.Count == 1);
                    args[0].Reevaluate((TypeSymbol)method.Parent);

                    return args[0];
                }
                else if ((method.Parent == stringType) &&
                         (method.Name.Equals("Escape", StringComparison.Ordinal) ||
                          method.Name.Equals("Unescape", StringComparison.Ordinal) ||
                          method.Name.Equals("EncodeUri", StringComparison.Ordinal) ||
                          method.Name.Equals("DecodeUri", StringComparison.Ordinal) ||
                          method.Name.Equals("EncodeUriComponent", StringComparison.Ordinal) ||
                          method.Name.Equals("DecodeUriComponent", StringComparison.Ordinal))) {
                    // String.<Method> becomes Script.<Method>, as its a global method in script
                    MethodSymbol scriptMethod = (MethodSymbol)scriptType.GetMember(method.Name);

                    methodExpression = new MethodExpression(new TypeExpression(scriptType, SymbolFilter.Public | SymbolFilter.StaticMembers),
                                                            scriptMethod);
                    methodExpression.AddParameterValue(memberExpression.ObjectReference);
                    return methodExpression;
                }
                else if ((method.Parent == scriptType) &&
                         method.Name.Equals("Literal", StringComparison.Ordinal)) {
                    // Convert a call to Script.Literal into a literal expression

                    Debug.Assert(args.Count >= 1);
                    string script = null;

                    if (args[0].Type == ExpressionType.Field) {
                        Debug.Assert(args[0].EvaluatedType == stringType);

                        FieldSymbol field = ((FieldExpression)args[0]).Field;
                        if (field.IsConstant) {
                            Debug.Assert(field.Value is string);
                            script = (string)field.Value;
                        }
                    }
                    else if (args[0].Type == ExpressionType.Literal) {
                        Debug.Assert(((LiteralExpression)args[0]).Value is string);
                        script = (string)((LiteralExpression)args[0]).Value;
                    }

                    if (script == null) {
                        // TODO: When we start raising errors at the expression level instead of the statement
                        //       level, we should return an ErrorExpression instead of a dummy expression.
                        Token argToken = argNodes.Expressions[0].Token;

                        _errorHandler.ReportError("The argument to Script.Literal must be a constant string.",
                                                  argToken.Location);
                        return new InlineScriptExpression("", objectType);
                    }

                    InlineScriptExpression scriptExpression = new InlineScriptExpression(script, objectType);
                    for (int i = 1; i < args.Count; i++) {
                        scriptExpression.AddParameterValue(args[i]);
                    }

                    return scriptExpression;
                }
                else if ((method.Parent == scriptType) &&
                         method.Name.Equals("Boolean", StringComparison.Ordinal)) {
                    Debug.Assert(args.Count == 1);

                    return new UnaryExpression(Operator.LogicalNot, new UnaryExpression(Operator.LogicalNot, args[0]));
                }
                else if ((method.Parent == scriptType) &&
                         method.Name.Equals("Value", StringComparison.Ordinal)) {
                    Debug.Assert(args.Count >= 2);

                    Expression expr = args[0];
                    for (int i = 1; i < args.Count; i++) {
                        expr = new BinaryExpression(Operator.LogicalOr, expr, args[i]);
                    }

                    expr.Reevaluate(args[0].EvaluatedType);
                    expr.AddParenthesisHint();

                    return expr;
                }
                else if (method.Parent == argsType) {
                    if (method.Name.Equals("GetArgument", StringComparison.Ordinal)) {
                        // Switch Arguments.GetArgument into Arguments[]
                        Debug.Assert(args.Count == 1);

                        IndexerExpression indexExpression =
                            new IndexerExpression(new LiteralExpression(typeType, method.Parent),
                                                  ((ClassSymbol)method.Parent).GetIndexer());
                        indexExpression.AddIndexParameterValue(args[0]);

                        return indexExpression;
                    }
                    else if (method.Name.Equals("ToArray", StringComparison.Ordinal)) {
                        // Switch Arguments.ToArray into Array.ToArray(arguments)

                        TypeSymbol arrayType = _symbolSet.ResolveIntrinsicType(IntrinsicType.Array);
                        MethodSymbol toArrayMethod = (MethodSymbol)arrayType.GetMember("ToArray");

                        InlineScriptExpression argsExpression =
                            new InlineScriptExpression("arguments", objectType, /* parenthesize */ false);
                        MethodExpression toArrayExpression =
                            new MethodExpression(new TypeExpression(arrayType, SymbolFilter.Public | SymbolFilter.StaticMembers),
                                                 toArrayMethod);
                        toArrayExpression.AddParameterValue(argsExpression);

                        return toArrayExpression;
                    }
                }
                else {
                    bool lateBound = false;

                    if (method.Parent == scriptType) {
                        LateBoundOperation lateBoundOperation = LateBoundOperation.InvokeMethod;

                        if (method.Name.Equals("InvokeMethod", StringComparison.Ordinal)) {
                            lateBound = true;
                        }
                        else if (method.Name.Equals("DeleteField", StringComparison.Ordinal)) {
                            lateBound = true;
                            lateBoundOperation = LateBoundOperation.DeleteField;
                        }
                        else if (method.Name.Equals("GetField", StringComparison.Ordinal)) {
                            lateBound = true;
                            lateBoundOperation = LateBoundOperation.GetField;
                        }
                        else if (method.Name.Equals("SetField", StringComparison.Ordinal)) {
                            lateBound = true;
                            lateBoundOperation = LateBoundOperation.SetField;
                        }
                        else if (method.Name.Equals("GetScriptType", StringComparison.Ordinal)) {
                            lateBound = true;
                            lateBoundOperation = LateBoundOperation.GetScriptType;
                        }
                        else if (method.Name.Equals("HasField", StringComparison.Ordinal)) {
                            lateBound = true;
                            lateBoundOperation = LateBoundOperation.HasField;
                        }
                        else if (method.Name.Equals("HasMethod", StringComparison.Ordinal)) {
                            lateBound = true;
                            lateBoundOperation = LateBoundOperation.HasMethod;
                        }
                        else if (method.Name.Equals("CreateInstance", StringComparison.Ordinal)) {
                            Debug.Assert(args.Count >= 1);

                            if ((args[0].Type == ExpressionType.MethodInvoke) ||
                                (args[0].Type == ExpressionType.PropertyGet)) {
                                // When using the result of a method call/property access directly
                                // with Type.CreateInstance, the following script would be generated:
                                //
                                // new method()()
                                // which is invalid. Instead we need to generate the following:
                                // var type = method();
                                // new type()

                                _errorHandler.ReportError("You must store the type returned from a method or property into a local variable to use with Type.CreateInstance.",
                                                          node.Token.Location);
                            }

                            NewExpression newExpression = new NewExpression(args[0], objectType);
                            if (args.Count > 1) {
                                bool first = true;
                                foreach (Expression paramExpr in args) {
                                    if (first) {
                                        first = false;
                                        continue;
                                    }
                                    newExpression.AddParameterValue(paramExpr);
                                }
                            }
                            return newExpression;
                        }

                        if (lateBound) {
                            // Switch explicit late-bound calls into implicit late-bound expressions
                            // in script
                            Debug.Assert((args != null) &&
                                         (((lateBoundOperation == LateBoundOperation.GetScriptType) && (args.Count == 1)) ||
                                          (args.Count >= 2)));

                            LateBoundExpression lateBoundExpression = null;
                            Expression instanceExpression = null;
                            Expression nameExpression = null;

                            foreach (Expression paramExpr in args) {
                                if (instanceExpression == null) {
                                    instanceExpression = paramExpr;

                                    if (lateBoundOperation == LateBoundOperation.GetScriptType) {
                                        // GetScriptType only takes an instance
                                        return new LateBoundExpression(instanceExpression, null,
                                                                       lateBoundOperation, objectType);
                                    }
                                    continue;
                                }
                                if (nameExpression == null) {
                                    nameExpression = paramExpr;

                                    Expression objectExpression = instanceExpression;
                                    if (lateBoundOperation == LateBoundOperation.InvokeMethod) {
                                        if ((instanceExpression.Type == ExpressionType.Literal) &&
                                            (((LiteralExpression)instanceExpression).Value == null)) {
                                            objectExpression = null;

                                            LiteralExpression literalExpression = nameExpression as LiteralExpression;
                                            if (literalExpression == null) {
                                                _errorHandler.ReportError("The name of a global method must be a constant string known at compile time.",
                                                                          argNodes.Expressions[0].Token.Location);
                                            }
                                            else if (!Utility.IsValidIdentifier((string)literalExpression.Value)) {
                                                _errorHandler.ReportError("The name of a global method must be a valid identifer.",
                                                                          argNodes.Expressions[0].Token.Location);
                                            }
                                        }
                                    }

                                    lateBoundExpression = new LateBoundExpression(objectExpression, nameExpression,
                                                                                  lateBoundOperation, objectType);
                                    continue;
                                }

                                lateBoundExpression.AddParameterValue(paramExpr);
                            }

                            Debug.Assert(lateBoundExpression != null);
                            return lateBoundExpression;
                        }
                    }

                    if (!method.MatchesConditions(_options.Defines)) {
                        return null;
                    }

                    methodExpression = new MethodExpression(memberExpression.ObjectReference,
                                                            method);
                }
            }

            if (args != null) {
                foreach (Expression paramExpr in args) {
                    methodExpression.AddParameterValue(paramExpr);
                }
            }

            if (isDelegateInvoke) {
                return new DelegateInvokeExpression(methodExpression);
            }
            return methodExpression;
        }
Example #2
0
        private Expression ProcessDotExpressionNode(BinaryExpressionNode node) {
            SymbolFilter filter = SymbolFilter.All;
            MemberSymbol memberSymbol = null;

            Expression objectExpression = ProcessDotExpressionNode(node, filter, out memberSymbol);
            if (objectExpression == null) {
                // We didn't successfully create an expression. The first pass attempted to
                // process the right child as an instance member of the left child expression.
                // We need to process the left child again as a type so we can process the
                // right child as a static member this time around.
                filter &= ~SymbolFilter.Members;
                objectExpression = ProcessDotExpressionNode(node, filter, out memberSymbol);
            }
            Debug.Assert(objectExpression != null);

            TypeSymbol dictionaryType = _symbolSet.ResolveIntrinsicType(IntrinsicType.Dictionary);
            TypeSymbol genericDictionaryType = _symbolSet.ResolveIntrinsicType(IntrinsicType.GenericDictionary);
            TypeSymbol nullableType = _symbolSet.ResolveIntrinsicType(IntrinsicType.Nullable);

            if (memberSymbol.Type == SymbolType.Property) {
                if ((memberSymbol.Parent == dictionaryType) ||
                    (memberSymbol.Parent == genericDictionaryType)) {
                    MethodSymbol methodSymbol = null;

                    if (String.CompareOrdinal(memberSymbol.Name, "Count") == 0) {
                        methodSymbol = (MethodSymbol)dictionaryType.GetMember("GetKeyCount");
                        Debug.Assert(methodSymbol != null);
                    }
                    else if (String.CompareOrdinal(memberSymbol.Name, "Keys") == 0) {
                        methodSymbol = (MethodSymbol)dictionaryType.GetMember("GetKeys");
                        Debug.Assert(methodSymbol != null);
                    }

                    if (methodSymbol != null) {
                        MethodExpression methodExpression =
                            new MethodExpression(new TypeExpression(dictionaryType, SymbolFilter.Public | SymbolFilter.StaticMembers),
                                                 methodSymbol);
                        methodExpression.AddParameterValue(objectExpression);
                        return methodExpression;
                    }
                }
                else if (memberSymbol.Parent == nullableType) {
                    if (String.CompareOrdinal(memberSymbol.Name, "Value") == 0) {
                        // Nullable<T>.Value becomes Nullable<T>

                        TypeSymbol underlyingType = objectExpression.EvaluatedType.GenericArguments.First();
                        objectExpression.Reevaluate(underlyingType);

                        return objectExpression;
                    }
                    else if (String.CompareOrdinal(memberSymbol.Name, "HasValue") == 0) {
                        // Nullable<T>.Value becomes Script.IsValue(Nullable<T>)

                        TypeSymbol scriptType = _symbolSet.ResolveIntrinsicType(IntrinsicType.Script);
                        MethodSymbol isValueMethod = (MethodSymbol)scriptType.GetMember("IsValue");

                        MethodExpression methodExpression
                            = new MethodExpression(new TypeExpression(scriptType, SymbolFilter.Public | SymbolFilter.StaticMembers),
                                                   isValueMethod);
                        methodExpression.AddParameterValue(objectExpression);

                        return methodExpression;
                    }
                }
            }
            else if (memberSymbol.Type == SymbolType.Method) {
                if (memberSymbol.Parent == nullableType) {
                    // Nullable<T>.GetValueOrDefault() becomes Nullable<T> || 0|false

                    TypeSymbol underlyingType = objectExpression.EvaluatedType.GenericArguments.First();

                    object defaultValue = 0;
                    if (underlyingType == _symbolSet.ResolveIntrinsicType(IntrinsicType.Boolean)) {
                        defaultValue = false;
                    }
                    else if (underlyingType == _symbolSet.ResolveIntrinsicType(IntrinsicType.String)) {
                        defaultValue = String.Empty;
                    }

                    LiteralExpression literalExpression = new LiteralExpression(underlyingType, defaultValue);

                    BinaryExpression logicalOrExpression = new BinaryExpression(Operator.LogicalOr, objectExpression, literalExpression);
                    logicalOrExpression.Reevaluate(underlyingType);
                    logicalOrExpression.AddParenthesisHint();

                    return logicalOrExpression;
                }
            }

            string dependency = ((TypeSymbol)memberSymbol.Parent).DependencyName;
            if (String.IsNullOrEmpty(dependency) == false) {
                _options.AddExecutionDependency(dependency);
            }

            MemberExpression expression = new MemberExpression(objectExpression, memberSymbol);
            if ((memberSymbol.Type == SymbolType.Method) &&
                memberSymbol.AssociatedType.IsGeneric && (memberSymbol.AssociatedType.GenericArguments == null)) {
                Debug.Assert(node.RightChild.NodeType == ParseNodeType.GenericName);
                Debug.Assert(((GenericNameNode)node.RightChild).TypeArguments != null);

                List<TypeSymbol> typeArgs = new List<TypeSymbol>();
                foreach (ParseNode typeArgNode in ((GenericNameNode)node.RightChild).TypeArguments) {
                    typeArgs.Add(_symbolSet.ResolveType(typeArgNode, _symbolTable, _symbolContext));
                }

                TypeSymbol returnType = _symbolSet.CreateGenericTypeSymbol(memberSymbol.AssociatedType, typeArgs);
                if (returnType != null) {
                    MethodSymbol genericMethod = (MethodSymbol)memberSymbol;
                    MethodSymbol instanceMethod = new MethodSymbol(genericMethod.Name, (TypeSymbol)genericMethod.Parent, returnType);

                    if (genericMethod.IsTransformed) {
                        instanceMethod.SetTransformedName(genericMethod.GeneratedName);
                    }
                    instanceMethod.SetNameCasing(genericMethod.IsCasePreserved);

                    expression = new MemberExpression(objectExpression, instanceMethod);
                }
            }

            return expression;
        }
Example #3
0
 public Expression TransformMemberExpression(MemberExpression expression, bool getOrAdd) {
     return TransformMemberExpression(expression, getOrAdd, /* isEventAddOrRemove */ false);
 }
Example #4
0
        public Expression TransformMemberExpression(MemberExpression expression, bool getOrAdd, bool isEventAddRemove) {
            switch (expression.Member.Type) {
                case SymbolType.EnumerationField:
                    if (((EnumerationSymbol)expression.Member.Parent).UseNamedValues) {
                        EnumerationFieldSymbol field = (EnumerationFieldSymbol)expression.Member;
                        string fieldName = ((EnumerationSymbol)expression.Member.Parent).CreateNamedValue(field);

                        return new LiteralExpression(_symbolSet.ResolveIntrinsicType(IntrinsicType.String),
                                                     fieldName);
                    }
                    else if (((TypeSymbol)expression.Member.Parent).IsApplicationType ||
                             ((EnumerationSymbol)expression.Member.Parent).UseNumericValues) {
                        // For enum types defined within the same assembly, simply use the literal value.
                        // Same goes for any enums marked as numeric values
                        return new LiteralExpression(_symbolSet.ResolveIntrinsicType(IntrinsicType.Integer),
                                                     ((EnumerationFieldSymbol)expression.Member).Value);
                    }
                    else {
                        // For enum types imported for another assembly
                        return new EnumerationFieldExpression(expression.ObjectReference,
                                                              (EnumerationFieldSymbol)expression.Member);
                    }
                case SymbolType.Field:
                    if (((FieldSymbol)expression.Member).IsConstant) {
                        return new LiteralExpression(expression.Member.AssociatedType, ((FieldSymbol)expression.Member).Value);
                    }
                    if (expression.ObjectReference is BaseExpression) {
                        // Create a this expression, because "this" works just as well as base.
                        // It is explicit, because the base was explicit.
                        return new FieldExpression(new ThisExpression(_classContext, /* explicitReference */ true),
                                                   (FieldSymbol)expression.Member);
                    }
                    if (((expression.Member.Visibility & MemberVisibility.Static) != 0) &&
                        (expression.Member.Parent != expression.ObjectReference.EvaluatedType)) {
                        // Create a new type expression because a static member
                        // of the base type is being used.
                        return new FieldExpression(new TypeExpression((ClassSymbol)expression.Member.Parent, expression.MemberMask),
                                                   (FieldSymbol)expression.Member);
                    }
                    if ((_symbolContext.Parent.Type == SymbolType.Record) &&
                        (expression.ObjectReference.Type == ExpressionType.This)) {
                        // Change "this" references inside struct ctor code to "$o"
                        VariableSymbol objectVariable = new VariableSymbol("$o", _memberContext, _classContext);
                        return new FieldExpression(new LocalExpression(objectVariable),
                                                   (FieldSymbol)expression.Member);
                    }
                    if (((expression.Member.Visibility & MemberVisibility.Static) != 0) &&
                        (expression.Member.Parent == _symbolSet.ResolveIntrinsicType(IntrinsicType.String)) &&
                        (String.CompareOrdinal(expression.Member.Name, "Empty") == 0)) {
                        // Convert String.Empty to literal expression
                        return new LiteralExpression(expression.Member.AssociatedType, String.Empty);
                    }
                    return new FieldExpression(expression.ObjectReference,
                                               (FieldSymbol)expression.Member);
                case SymbolType.Property:
                    return new PropertyExpression(expression.ObjectReference,
                                                  (PropertySymbol)expression.Member, getOrAdd);
                case SymbolType.Method:
                    Debug.Assert(getOrAdd);
                    return new DelegateExpression(expression.ObjectReference,
                                                  (MethodSymbol)expression.Member);
                case SymbolType.Event:
                    if (isEventAddRemove) {
                        return new EventExpression(expression.ObjectReference,
                                                   (EventSymbol)expression.Member, getOrAdd);
                    }
                    else {
                        Debug.Assert(((EventSymbol)expression.Member).DefaultImplementation);

                        // When the field corresponding to an event whose accessors are auto-generated is
                        // referenced, we need to hunt for a special generated field name (this is the
                        // field that is added to the class).

                        string fieldName = "__" + Utility.CreateCamelCaseName(expression.Member.Name);
                        FieldSymbol fieldSymbol = (FieldSymbol)expression.ObjectReference.EvaluatedType.GetMember(fieldName);
                        Debug.Assert(fieldSymbol != null);

                        if (expression.ObjectReference is BaseExpression) {
                            // Create a this expression, because "this" works just as well as base.
                            // It is explicit, because the base was explicit.
                            return new FieldExpression(new ThisExpression(_classContext, /* explicitReference */ true),
                                                       fieldSymbol);
                        }
                        return new FieldExpression(expression.ObjectReference, fieldSymbol);
                    }
                default:
                    Debug.Fail("Unexpected member type to transform: " + expression.Member.Type);
                    break;
            }
            return expression;
        }
Example #5
0
 public Expression TransformMemberExpression(MemberExpression expression) {
     return TransformMemberExpression(expression, /* getOrAdd */ true, /* isEventAddOrRemove */ false);
 }