~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
ļ»æ// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
 
2
// 
 
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
 
4
// software and associated documentation files (the "Software"), to deal in the Software
 
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
 
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
 
7
// to whom the Software is furnished to do so, subject to the following conditions:
 
8
// 
 
9
// The above copyright notice and this permission notice shall be included in all copies or
 
10
// substantial portions of the Software.
 
11
// 
 
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
17
// DEALINGS IN THE SOFTWARE.
 
18
 
 
19
using System;
 
20
using System.Collections.Generic;
 
21
using System.Linq;
 
22
using ICSharpCode.NRefactory.CSharp.Analysis;
 
23
using ICSharpCode.NRefactory.CSharp.Resolver;
 
24
using ICSharpCode.NRefactory.Semantics;
 
25
using ICSharpCode.NRefactory.TypeSystem;
 
26
using ICSharpCode.NRefactory.TypeSystem.Implementation;
 
27
using ICSharpCode.NRefactory.Utils;
 
28
 
 
29
namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues
 
30
{
 
31
        // Contains representations for constant C# expressions.
 
32
        // We use these instead of storing the full AST to reduce the memory usage.
 
33
        
 
34
        [Serializable]
 
35
        public abstract class ConstantExpression : IConstantValue
 
36
        {
 
37
                public abstract ResolveResult Resolve(CSharpResolver resolver);
 
38
                
 
39
                public ResolveResult Resolve(ITypeResolveContext context)
 
40
                {
 
41
                        var csContext = (CSharpTypeResolveContext)context;
 
42
                        if (context.CurrentAssembly != context.Compilation.MainAssembly) {
 
43
                                // The constant needs to be resolved in a different compilation.
 
44
                                IProjectContent pc = context.CurrentAssembly as IProjectContent;
 
45
                                if (pc != null) {
 
46
                                        ICompilation nestedCompilation = context.Compilation.SolutionSnapshot.GetCompilation(pc);
 
47
                                        if (nestedCompilation != null) {
 
48
                                                var nestedContext = MapToNestedCompilation(csContext, nestedCompilation);
 
49
                                                ResolveResult rr = Resolve(new CSharpResolver(nestedContext));
 
50
                                                return MapToNewContext(rr, context);
 
51
                                        }
 
52
                                }
 
53
                        }
 
54
                        // Resolve in current context.
 
55
                        return Resolve(new CSharpResolver(csContext));
 
56
                }
 
57
                
 
58
                CSharpTypeResolveContext MapToNestedCompilation(CSharpTypeResolveContext context, ICompilation nestedCompilation)
 
59
                {
 
60
                        var nestedContext = new CSharpTypeResolveContext(nestedCompilation.MainAssembly);
 
61
                        if (context.CurrentUsingScope != null) {
 
62
                                nestedContext = nestedContext.WithUsingScope(context.CurrentUsingScope.UnresolvedUsingScope.Resolve(nestedCompilation));
 
63
                        }
 
64
                        if (context.CurrentTypeDefinition != null) {
 
65
                                nestedContext = nestedContext.WithCurrentTypeDefinition(nestedCompilation.Import(context.CurrentTypeDefinition));
 
66
                        }
 
67
                        return nestedContext;
 
68
                }
 
69
                
 
70
                static ResolveResult MapToNewContext(ResolveResult rr, ITypeResolveContext newContext)
 
71
                {
 
72
                        if (rr is TypeOfResolveResult) {
 
73
                                return new TypeOfResolveResult(
 
74
                                        rr.Type.ToTypeReference().Resolve(newContext),
 
75
                                        ((TypeOfResolveResult)rr).ReferencedType.ToTypeReference().Resolve(newContext));
 
76
                        } else if (rr is ArrayCreateResolveResult) {
 
77
                                ArrayCreateResolveResult acrr = (ArrayCreateResolveResult)rr;
 
78
                                return new ArrayCreateResolveResult(
 
79
                                        acrr.Type.ToTypeReference().Resolve(newContext),
 
80
                                        MapToNewContext(acrr.SizeArguments, newContext),
 
81
                                        MapToNewContext(acrr.InitializerElements, newContext));
 
82
                        } else if (rr.IsCompileTimeConstant) {
 
83
                                return new ConstantResolveResult(
 
84
                                        rr.Type.ToTypeReference().Resolve(newContext),
 
85
                                        rr.ConstantValue
 
86
                                );
 
87
                        } else {
 
88
                                return new ErrorResolveResult(rr.Type.ToTypeReference().Resolve(newContext));
 
89
                        }
 
90
                }
 
91
                
 
92
                static ResolveResult[] MapToNewContext(IList<ResolveResult> input, ITypeResolveContext newContext)
 
93
                {
 
94
                        if (input == null)
 
95
                                return null;
 
96
                        ResolveResult[] output = new ResolveResult[input.Count];
 
97
                        for (int i = 0; i < output.Length; i++) {
 
98
                                output[i] = MapToNewContext(input[i], newContext);
 
99
                        }
 
100
                        return output;
 
101
                }
 
102
        }
 
103
        
 
104
        /// <summary>
 
105
        /// Used for constants that could not be converted to IConstantValue.
 
106
        /// </summary>
 
107
        [Serializable]
 
108
        public sealed class ErrorConstantValue : IConstantValue
 
109
        {
 
110
                readonly ITypeReference type;
 
111
                
 
112
                public ErrorConstantValue(ITypeReference type)
 
113
                {
 
114
                        if (type == null)
 
115
                                throw new ArgumentNullException("type");
 
116
                        this.type = type;
 
117
                }
 
118
                
 
119
                public ResolveResult Resolve(ITypeResolveContext context)
 
120
                {
 
121
                        return new ErrorResolveResult(type.Resolve(context));
 
122
                }
 
123
        }
 
124
        
 
125
        /// <summary>
 
126
        /// Increments an integer <see cref="IConstantValue"/> by a fixed amount without changing the type.
 
127
        /// </summary>
 
128
        [Serializable]
 
129
        public sealed class IncrementConstantValue : IConstantValue, ISupportsInterning
 
130
        {
 
131
                readonly IConstantValue baseValue;
 
132
                readonly int incrementAmount;
 
133
                
 
134
                public IncrementConstantValue(IConstantValue baseValue, int incrementAmount = 1)
 
135
                {
 
136
                        if (baseValue == null)
 
137
                                throw new ArgumentNullException("baseValue");
 
138
                        IncrementConstantValue icv = baseValue as IncrementConstantValue;
 
139
                        if (icv != null) {
 
140
                                this.baseValue = icv.baseValue;
 
141
                                this.incrementAmount = icv.incrementAmount + incrementAmount;
 
142
                        } else {
 
143
                                this.baseValue = baseValue;
 
144
                                this.incrementAmount = incrementAmount;
 
145
                        }
 
146
                }
 
147
                
 
148
                public ResolveResult Resolve(ITypeResolveContext context)
 
149
                {
 
150
                        ResolveResult rr = baseValue.Resolve(context);
 
151
                        if (rr.IsCompileTimeConstant && rr.ConstantValue != null) {
 
152
                                object val = rr.ConstantValue;
 
153
                                TypeCode typeCode = Type.GetTypeCode(val.GetType());
 
154
                                if (typeCode >= TypeCode.SByte && typeCode <= TypeCode.UInt64) {
 
155
                                        long intVal = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, val, false);
 
156
                                        object newVal = CSharpPrimitiveCast.Cast(typeCode, unchecked(intVal + incrementAmount), false);
 
157
                                        return new ConstantResolveResult(rr.Type, newVal);
 
158
                                }
 
159
                        }
 
160
                        return new ErrorResolveResult(rr.Type);
 
161
                }
 
162
                
 
163
                int ISupportsInterning.GetHashCodeForInterning()
 
164
                {
 
165
                        unchecked {
 
166
                                return baseValue.GetHashCode() * 33 ^ incrementAmount;
 
167
                        }
 
168
                }
 
169
                
 
170
                bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
 
171
                {
 
172
                        IncrementConstantValue o = other as IncrementConstantValue;
 
173
                        return o != null && baseValue == o.baseValue && incrementAmount == o.incrementAmount;
 
174
                }
 
175
        }
 
176
        
 
177
        /// <summary>
 
178
        /// C#'s equivalent to the SimpleConstantValue.
 
179
        /// </summary>
 
180
        [Serializable]
 
181
        public sealed class PrimitiveConstantExpression : ConstantExpression, ISupportsInterning
 
182
        {
 
183
                readonly ITypeReference type;
 
184
                readonly object value;
 
185
                
 
186
                public ITypeReference Type {
 
187
                        get { return type; }
 
188
                }
 
189
                
 
190
                public object Value {
 
191
                        get { return value; }
 
192
                }
 
193
                
 
194
                public PrimitiveConstantExpression(ITypeReference type, object value)
 
195
                {
 
196
                        if (type == null)
 
197
                                throw new ArgumentNullException("type");
 
198
                        this.type = type;
 
199
                        this.value = value;
 
200
                }
 
201
                
 
202
                public override ResolveResult Resolve(CSharpResolver resolver)
 
203
                {
 
204
                        return new ConstantResolveResult(type.Resolve(resolver.CurrentTypeResolveContext), value);
 
205
                }
 
206
                
 
207
                int ISupportsInterning.GetHashCodeForInterning()
 
208
                {
 
209
                        return type.GetHashCode() ^ (value != null ? value.GetHashCode() : 0);
 
210
                }
 
211
                
 
212
                bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
 
213
                {
 
214
                        PrimitiveConstantExpression scv = other as PrimitiveConstantExpression;
 
215
                        return scv != null && type == scv.type && value == scv.value;
 
216
                }
 
217
        }
 
218
        
 
219
        [Serializable]
 
220
        public sealed class TypeOfConstantExpression : ConstantExpression
 
221
        {
 
222
                readonly ITypeReference type;
 
223
                
 
224
                public ITypeReference Type {
 
225
                        get { return type; }
 
226
                }
 
227
                
 
228
                public TypeOfConstantExpression(ITypeReference type)
 
229
                {
 
230
                        this.type = type;
 
231
                }
 
232
                
 
233
                public override ResolveResult Resolve(CSharpResolver resolver)
 
234
                {
 
235
                        return resolver.ResolveTypeOf(type.Resolve(resolver.CurrentTypeResolveContext));
 
236
                }
 
237
        }
 
238
        
 
239
        [Serializable]
 
240
        public sealed class ConstantCast : ConstantExpression, ISupportsInterning
 
241
        {
 
242
                readonly ITypeReference targetType;
 
243
                readonly ConstantExpression expression;
 
244
                
 
245
                public ConstantCast(ITypeReference targetType, ConstantExpression expression)
 
246
                {
 
247
                        if (targetType == null)
 
248
                                throw new ArgumentNullException("targetType");
 
249
                        if (expression == null)
 
250
                                throw new ArgumentNullException("expression");
 
251
                        this.targetType = targetType;
 
252
                        this.expression = expression;
 
253
                }
 
254
                
 
255
                public override ResolveResult Resolve(CSharpResolver resolver)
 
256
                {
 
257
                        return resolver.ResolveCast(targetType.Resolve(resolver.CurrentTypeResolveContext), expression.Resolve(resolver));
 
258
                }
 
259
                
 
260
                int ISupportsInterning.GetHashCodeForInterning()
 
261
                {
 
262
                        unchecked {
 
263
                                return targetType.GetHashCode() + expression.GetHashCode() * 1018829;
 
264
                        }
 
265
                }
 
266
                
 
267
                bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
 
268
                {
 
269
                        ConstantCast cast = other as ConstantCast;
 
270
                        return cast != null
 
271
                                && this.targetType == cast.targetType && this.expression == cast.expression;
 
272
                }
 
273
        }
 
274
        
 
275
        [Serializable]
 
276
        public sealed class ConstantIdentifierReference : ConstantExpression
 
277
        {
 
278
                readonly string identifier;
 
279
                readonly IList<ITypeReference> typeArguments;
 
280
                
 
281
                public ConstantIdentifierReference(string identifier, IList<ITypeReference> typeArguments = null)
 
282
                {
 
283
                        if (identifier == null)
 
284
                                throw new ArgumentNullException("identifier");
 
285
                        this.identifier = identifier;
 
286
                        this.typeArguments = typeArguments ?? EmptyList<ITypeReference>.Instance;
 
287
                }
 
288
                
 
289
                public override ResolveResult Resolve(CSharpResolver resolver)
 
290
                {
 
291
                        return resolver.ResolveSimpleName(identifier, typeArguments.Resolve(resolver.CurrentTypeResolveContext));
 
292
                }
 
293
        }
 
294
        
 
295
        [Serializable]
 
296
        public sealed class ConstantMemberReference : ConstantExpression
 
297
        {
 
298
                readonly ITypeReference targetType;
 
299
                readonly ConstantExpression targetExpression;
 
300
                readonly string memberName;
 
301
                readonly IList<ITypeReference> typeArguments;
 
302
                
 
303
                public ConstantMemberReference(ITypeReference targetType, string memberName, IList<ITypeReference> typeArguments = null)
 
304
                {
 
305
                        if (targetType == null)
 
306
                                throw new ArgumentNullException("targetType");
 
307
                        if (memberName == null)
 
308
                                throw new ArgumentNullException("memberName");
 
309
                        this.targetType = targetType;
 
310
                        this.memberName = memberName;
 
311
                        this.typeArguments = typeArguments ?? EmptyList<ITypeReference>.Instance;
 
312
                }
 
313
                
 
314
                public ConstantMemberReference(ConstantExpression targetExpression, string memberName, IList<ITypeReference> typeArguments = null)
 
315
                {
 
316
                        if (targetExpression == null)
 
317
                                throw new ArgumentNullException("targetExpression");
 
318
                        if (memberName == null)
 
319
                                throw new ArgumentNullException("memberName");
 
320
                        this.targetExpression = targetExpression;
 
321
                        this.memberName = memberName;
 
322
                        this.typeArguments = typeArguments ?? EmptyList<ITypeReference>.Instance;
 
323
                }
 
324
                
 
325
                public override ResolveResult Resolve(CSharpResolver resolver)
 
326
                {
 
327
                        ResolveResult rr;
 
328
                        if (targetType != null)
 
329
                                rr = new TypeResolveResult(targetType.Resolve(resolver.CurrentTypeResolveContext));
 
330
                        else
 
331
                                rr = targetExpression.Resolve(resolver);
 
332
                        return resolver.ResolveMemberAccess(rr, memberName, typeArguments.Resolve(resolver.CurrentTypeResolveContext));
 
333
                }
 
334
        }
 
335
        
 
336
        [Serializable]
 
337
        public sealed class ConstantCheckedExpression : ConstantExpression
 
338
        {
 
339
                readonly bool checkForOverflow;
 
340
                readonly ConstantExpression expression;
 
341
                
 
342
                public ConstantCheckedExpression(bool checkForOverflow, ConstantExpression expression)
 
343
                {
 
344
                        if (expression == null)
 
345
                                throw new ArgumentNullException("expression");
 
346
                        this.checkForOverflow = checkForOverflow;
 
347
                        this.expression = expression;
 
348
                }
 
349
                
 
350
                public override ResolveResult Resolve(CSharpResolver resolver)
 
351
                {
 
352
                        return expression.Resolve(resolver.WithCheckForOverflow(checkForOverflow));
 
353
                }
 
354
        }
 
355
        
 
356
        [Serializable]
 
357
        public sealed class ConstantDefaultValue : ConstantExpression, ISupportsInterning
 
358
        {
 
359
                readonly ITypeReference type;
 
360
                
 
361
                public ConstantDefaultValue(ITypeReference type)
 
362
                {
 
363
                        if (type == null)
 
364
                                throw new ArgumentNullException("type");
 
365
                        this.type = type;
 
366
                }
 
367
                
 
368
                public override ResolveResult Resolve(CSharpResolver resolver)
 
369
                {
 
370
                        return resolver.ResolveDefaultValue(type.Resolve(resolver.CurrentTypeResolveContext));
 
371
                }
 
372
                
 
373
                int ISupportsInterning.GetHashCodeForInterning()
 
374
                {
 
375
                        return type.GetHashCode();
 
376
                }
 
377
                
 
378
                bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
 
379
                {
 
380
                        ConstantDefaultValue o = other as ConstantDefaultValue;
 
381
                        return o != null && this.type == o.type;
 
382
                }
 
383
        }
 
384
        
 
385
        [Serializable]
 
386
        public sealed class ConstantUnaryOperator : ConstantExpression
 
387
        {
 
388
                readonly UnaryOperatorType operatorType;
 
389
                readonly ConstantExpression expression;
 
390
                
 
391
                public ConstantUnaryOperator(UnaryOperatorType operatorType, ConstantExpression expression)
 
392
                {
 
393
                        if (expression == null)
 
394
                                throw new ArgumentNullException("expression");
 
395
                        this.operatorType = operatorType;
 
396
                        this.expression = expression;
 
397
                }
 
398
                
 
399
                public override ResolveResult Resolve(CSharpResolver resolver)
 
400
                {
 
401
                        return resolver.ResolveUnaryOperator(operatorType, expression.Resolve(resolver));
 
402
                }
 
403
        }
 
404
 
 
405
        [Serializable]
 
406
        public sealed class ConstantBinaryOperator : ConstantExpression
 
407
        {
 
408
                readonly ConstantExpression left;
 
409
                readonly BinaryOperatorType operatorType;
 
410
                readonly ConstantExpression right;
 
411
                
 
412
                public ConstantBinaryOperator(ConstantExpression left, BinaryOperatorType operatorType, ConstantExpression right)
 
413
                {
 
414
                        if (left == null)
 
415
                                throw new ArgumentNullException("left");
 
416
                        if (right == null)
 
417
                                throw new ArgumentNullException("right");
 
418
                        this.left = left;
 
419
                        this.operatorType = operatorType;
 
420
                        this.right = right;
 
421
                }
 
422
                
 
423
                public override ResolveResult Resolve(CSharpResolver resolver)
 
424
                {
 
425
                        ResolveResult lhs = left.Resolve(resolver);
 
426
                        ResolveResult rhs = right.Resolve(resolver);
 
427
                        return resolver.ResolveBinaryOperator(operatorType, lhs, rhs);
 
428
                }
 
429
        }
 
430
        
 
431
        [Serializable]
 
432
        public sealed class ConstantConditionalOperator : ConstantExpression
 
433
        {
 
434
                readonly ConstantExpression condition, trueExpr, falseExpr;
 
435
                
 
436
                public ConstantConditionalOperator(ConstantExpression condition, ConstantExpression trueExpr, ConstantExpression falseExpr)
 
437
                {
 
438
                        if (condition == null)
 
439
                                throw new ArgumentNullException("condition");
 
440
                        if (trueExpr == null)
 
441
                                throw new ArgumentNullException("trueExpr");
 
442
                        if (falseExpr == null)
 
443
                                throw new ArgumentNullException("falseExpr");
 
444
                        this.condition = condition;
 
445
                        this.trueExpr = trueExpr;
 
446
                        this.falseExpr = falseExpr;
 
447
                }
 
448
                
 
449
                public override ResolveResult Resolve(CSharpResolver resolver)
 
450
                {
 
451
                        return resolver.ResolveConditional(
 
452
                                condition.Resolve(resolver),
 
453
                                trueExpr.Resolve(resolver),
 
454
                                falseExpr.Resolve(resolver)
 
455
                        );
 
456
                }
 
457
        }
 
458
        
 
459
        /// <summary>
 
460
        /// Represents an array creation (as used within an attribute argument)
 
461
        /// </summary>
 
462
        [Serializable]
 
463
        public sealed class ConstantArrayCreation : ConstantExpression
 
464
        {
 
465
                // type may be null when the element is being inferred
 
466
                readonly ITypeReference elementType;
 
467
                readonly IList<ConstantExpression> arrayElements;
 
468
                
 
469
                public ConstantArrayCreation(ITypeReference type, IList<ConstantExpression> arrayElements)
 
470
                {
 
471
                        if (arrayElements == null)
 
472
                                throw new ArgumentNullException("arrayElements");
 
473
                        this.elementType = type;
 
474
                        this.arrayElements = arrayElements;
 
475
                }
 
476
                
 
477
                public override ResolveResult Resolve(CSharpResolver resolver)
 
478
                {
 
479
                        ResolveResult[] elements = new ResolveResult[arrayElements.Count];
 
480
                        for (int i = 0; i < elements.Length; i++) {
 
481
                                elements[i] = arrayElements[i].Resolve(resolver);
 
482
                        }
 
483
                        int[] sizeArguments = { elements.Length };
 
484
                        if (elementType != null) {
 
485
                                return resolver.ResolveArrayCreation(elementType.Resolve(resolver.CurrentTypeResolveContext), sizeArguments, elements);
 
486
                        } else {
 
487
                                return resolver.ResolveArrayCreation(null, sizeArguments, elements);
 
488
                        }
 
489
                }
 
490
        }
 
491
 
 
492
        /// <summary>
 
493
        /// Used for sizeof() expressions in constants.
 
494
        /// </summary>
 
495
        [Serializable]
 
496
        public sealed class SizeOfConstantValue : ConstantExpression
 
497
        {
 
498
                readonly ITypeReference type;
 
499
                
 
500
                public SizeOfConstantValue(ITypeReference type)
 
501
                {
 
502
                        if (type == null)
 
503
                                throw new ArgumentNullException("type");
 
504
                        this.type = type;
 
505
                }
 
506
                
 
507
                public override ResolveResult Resolve(CSharpResolver resolver)
 
508
                {
 
509
                        return resolver.ResolveSizeOf(type.Resolve(resolver.CurrentTypeResolveContext));
 
510
                }
 
511
        }
 
512
}