Implemented overloaded versions of Parse and TryParse functions for BigInteger.
[mono.git] / mcs / mcs / context.cs
1 //
2 // context.cs: Various compiler contexts.
3 //
4 // Author:
5 //   Marek Safar (marek.safar@gmail.com)
6 //   Miguel de Icaza (miguel@ximian.com)
7 //
8 // Copyright 2001, 2002, 2003 Ximian, Inc.
9 // Copyright 2004-2009 Novell, Inc.
10 // Copyright 2011 Xamarin Inc.
11 //
12
13 using System;
14 using System.Collections.Generic;
15 using System.IO;
16 using System.Security.Cryptography;
17
18 namespace Mono.CSharp
19 {
20         public enum LookupMode
21         {
22                 Normal = 0,
23                 Probing = 1,
24                 IgnoreAccessibility = 2
25         }
26
27         //
28         // Implemented by elements which can act as independent contexts
29         // during resolve phase. Used mostly for lookups.
30         //
31         public interface IMemberContext : IModuleContext
32         {
33                 //
34                 // A scope type context, it can be inflated for generic types
35                 //
36                 TypeSpec CurrentType { get; }
37
38                 //
39                 // A scope type parameters either VAR or MVAR
40                 //
41                 TypeParameters CurrentTypeParameters { get; }
42
43                 //
44                 // A member definition of the context. For partial types definition use
45                 // CurrentTypeDefinition.PartialContainer otherwise the context is local
46                 //
47                 // TODO: Obsolete it in this context, dynamic context cannot guarantee sensible value
48                 //
49                 MemberCore CurrentMemberDefinition { get; }
50
51                 bool IsObsolete { get; }
52                 bool IsUnsafe { get; }
53                 bool IsStatic { get; }
54
55                 string GetSignatureForError ();
56
57                 ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity);
58                 FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc);
59                 FullNamedExpression LookupNamespaceAlias (string name);
60         }
61
62         public interface IModuleContext
63         {
64                 ModuleContainer Module { get; }
65         }
66
67         //
68         // Block or statement resolving context
69         //
70         public class BlockContext : ResolveContext
71         {
72                 readonly TypeSpec return_type;
73
74                 //
75                 // Tracks the last offset used by VariableInfo
76                 //
77                 public int AssignmentInfoOffset;
78
79                 public BlockContext (IMemberContext mc, ExplicitBlock block, TypeSpec returnType)
80                         : base (mc)
81                 {
82                         if (returnType == null)
83                                 throw new ArgumentNullException ("returnType");
84
85                         this.return_type = returnType;
86
87                         // TODO: check for null value
88                         CurrentBlock = block;
89                 }
90
91                 public BlockContext (ResolveContext rc, ExplicitBlock block, TypeSpec returnType)
92                         : this (rc.MemberContext, block, returnType)
93                 {
94                         if (rc.IsUnsafe)
95                                 flags |= ResolveContext.Options.UnsafeScope;
96
97                         if (rc.HasSet (ResolveContext.Options.CheckedScope))
98                                 flags |= ResolveContext.Options.CheckedScope;
99
100                         if (rc.IsInProbingMode)
101                                 flags |= ResolveContext.Options.ProbingMode;
102
103                         if (rc.HasSet (ResolveContext.Options.FieldInitializerScope))
104                                 flags |= ResolveContext.Options.FieldInitializerScope;
105
106                         if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion))
107                                 flags |= ResolveContext.Options.ExpressionTreeConversion;
108
109                         if (rc.HasSet (ResolveContext.Options.BaseInitializer))
110                                 flags |= ResolveContext.Options.BaseInitializer;
111                 }
112
113                 public ExceptionStatement CurrentTryBlock { get; set; }
114
115                 public LoopStatement EnclosingLoop { get; set; }
116
117                 public LoopStatement EnclosingLoopOrSwitch { get; set; }
118
119                 public Switch Switch { get; set; }
120
121                 public TypeSpec ReturnType {
122                         get { return return_type; }
123                 }
124         }
125
126         //
127         // Expression resolving context
128         //
129         public class ResolveContext : IMemberContext
130         {
131                 [Flags]
132                 public enum Options
133                 {
134                         /// <summary>
135                         ///   This flag tracks the `checked' state of the compilation,
136                         ///   it controls whether we should generate code that does overflow
137                         ///   checking, or if we generate code that ignores overflows.
138                         ///
139                         ///   The default setting comes from the command line option to generate
140                         ///   checked or unchecked code plus any source code changes using the
141                         ///   checked/unchecked statements or expressions.   Contrast this with
142                         ///   the ConstantCheckState flag.
143                         /// </summary>
144                         CheckedScope = 1 << 0,
145
146                         /// <summary>
147                         ///   The constant check state is always set to `true' and cant be changed
148                         ///   from the command line.  The source code can change this setting with
149                         ///   the `checked' and `unchecked' statements and expressions. 
150                         /// </summary>
151                         ConstantCheckState = 1 << 1,
152
153                         AllCheckStateFlags = CheckedScope | ConstantCheckState,
154
155                         //
156                         // unsafe { ... } scope
157                         //
158                         UnsafeScope = 1 << 2,
159                         CatchScope = 1 << 3,
160                         FinallyScope = 1 << 4,
161                         FieldInitializerScope = 1 << 5,
162                         CompoundAssignmentScope = 1 << 6,
163                         FixedInitializerScope = 1 << 7,
164                         BaseInitializer = 1 << 8,
165
166                         //
167                         // Inside an enum definition, we do not resolve enumeration values
168                         // to their enumerations, but rather to the underlying type/value
169                         // This is so EnumVal + EnumValB can be evaluated.
170                         //
171                         // There is no "E operator + (E x, E y)", so during an enum evaluation
172                         // we relax the rules
173                         //
174                         EnumScope = 1 << 9,
175
176                         ConstantScope = 1 << 10,
177
178                         ConstructorScope = 1 << 11,
179
180                         UsingInitializerScope = 1 << 12,
181
182                         LockScope = 1 << 13,
183
184                         TryScope = 1 << 14,
185
186                         TryWithCatchScope = 1 << 15,
187
188                         ///
189                         /// Indicates the current context is in probing mode, no errors are reported. 
190                         ///
191                         ProbingMode = 1 << 22,
192
193                         //
194                         // Return and ContextualReturn statements will set the ReturnType
195                         // value based on the expression types of each return statement
196                         // instead of the method return type which is initially null.
197                         //
198                         InferReturnType = 1 << 23,
199
200                         OmitDebuggingInfo = 1 << 24,
201
202                         ExpressionTreeConversion = 1 << 25,
203
204                         InvokeSpecialName = 1 << 26
205                 }
206
207                 // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements
208                 // it's public so that we can use a struct at the callsite
209                 public struct FlagsHandle : IDisposable
210                 {
211                         readonly ResolveContext ec;
212                         readonly Options invmask, oldval;
213
214                         public FlagsHandle (ResolveContext ec, Options flagsToSet)
215                                 : this (ec, flagsToSet, flagsToSet)
216                         {
217                         }
218
219                         internal FlagsHandle (ResolveContext ec, Options mask, Options val)
220                         {
221                                 this.ec = ec;
222                                 invmask = ~mask;
223                                 oldval = ec.flags & mask;
224                                 ec.flags = (ec.flags & invmask) | (val & mask);
225
226 //                              if ((mask & Options.ProbingMode) != 0)
227 //                                      ec.Report.DisableReporting ();
228                         }
229
230                         public void Dispose ()
231                         {
232 //                              if ((invmask & Options.ProbingMode) == 0)
233 //                                      ec.Report.EnableReporting ();
234
235                                 ec.flags = (ec.flags & invmask) | oldval;
236                         }
237                 }
238
239                 protected Options flags;
240
241                 //
242                 // Whether we are inside an anonymous method.
243                 //
244                 public AnonymousExpression CurrentAnonymousMethod;
245
246                 //
247                 // Holds a varible used during collection or object initialization.
248                 //
249                 public Expression CurrentInitializerVariable;
250
251                 public Block CurrentBlock;
252
253                 public readonly IMemberContext MemberContext;
254
255                 public ResolveContext (IMemberContext mc)
256                 {
257                         if (mc == null)
258                                 throw new ArgumentNullException ();
259
260                         MemberContext = mc;
261
262                         //
263                         // The default setting comes from the command line option
264                         //
265                         if (mc.Module.Compiler.Settings.Checked)
266                                 flags |= Options.CheckedScope;
267
268                         //
269                         // The constant check state is always set to true
270                         //
271                         flags |= Options.ConstantCheckState;
272                 }
273
274                 public ResolveContext (IMemberContext mc, Options options)
275                         : this (mc)
276                 {
277                         flags |= options;
278                 }
279
280                 #region Properties
281
282                 public BuiltinTypes BuiltinTypes {
283                         get {
284                                 return MemberContext.Module.Compiler.BuiltinTypes;
285                         }
286                 }
287
288                 public virtual ExplicitBlock ConstructorBlock {
289                         get {
290                                 return CurrentBlock.Explicit;
291                         }
292                 }
293
294                 //
295                 // The current iterator
296                 //
297                 public Iterator CurrentIterator {
298                         get { return CurrentAnonymousMethod as Iterator; }
299                 }
300
301                 public TypeSpec CurrentType {
302                         get { return MemberContext.CurrentType; }
303                 }
304
305                 public TypeParameters CurrentTypeParameters {
306                         get { return MemberContext.CurrentTypeParameters; }
307                 }
308
309                 public MemberCore CurrentMemberDefinition {
310                         get { return MemberContext.CurrentMemberDefinition; }
311                 }
312
313                 public bool ConstantCheckState {
314                         get { return (flags & Options.ConstantCheckState) != 0; }
315                 }
316
317                 public bool IsInProbingMode {
318                         get {
319                                 return (flags & Options.ProbingMode) != 0;
320                         }
321                 }
322
323                 public bool IsObsolete {
324                         get {
325                                 // Disables obsolete checks when probing is on
326                                 return MemberContext.IsObsolete;
327                         }
328                 }
329
330                 public bool IsStatic {
331                         get {
332                                 return MemberContext.IsStatic;
333                         }
334                 }
335
336                 public bool IsUnsafe {
337                         get {
338                                 return HasSet (Options.UnsafeScope) || MemberContext.IsUnsafe;
339                         }
340                 }
341
342                 public bool IsRuntimeBinder {
343                         get {
344                                 return Module.Compiler.IsRuntimeBinder;
345                         }
346                 }
347
348                 public bool IsVariableCapturingRequired {
349                         get {
350                                 return !IsInProbingMode;
351                         }
352                 }
353
354                 public ModuleContainer Module {
355                         get {
356                                 return MemberContext.Module;
357                         }
358                 }
359
360                 public Report Report {
361                         get {
362                                 return Module.Compiler.Report;
363                         }
364                 }
365
366                 #endregion
367
368                 public bool MustCaptureVariable (INamedBlockVariable local)
369                 {
370                         if (CurrentAnonymousMethod == null)
371                                 return false;
372
373                         //
374                         // Capture only if this or any of child blocks contain yield
375                         // or it's a parameter
376                         //
377                         if (CurrentAnonymousMethod.IsIterator)
378                                 return local.IsParameter || local.Block.Explicit.HasYield;
379
380                         //
381                         // Capture only if this or any of child blocks contain await
382                         // or it's a parameter or we need to access variable from 
383                         // different parameter block
384                         //
385                         if (CurrentAnonymousMethod is AsyncInitializer)
386                                 return local.IsParameter || local.Block.Explicit.HasAwait || CurrentBlock.Explicit.HasAwait ||
387                                         local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original;
388
389                         return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original;
390                 }
391
392                 public bool HasSet (Options options)
393                 {
394                         return (this.flags & options) == options;
395                 }
396
397                 public bool HasAny (Options options)
398                 {
399                         return (this.flags & options) != 0;
400                 }
401
402
403                 // Temporarily set all the given flags to the given value.  Should be used in an 'using' statement
404                 public FlagsHandle Set (Options options)
405                 {
406                         return new FlagsHandle (this, options);
407                 }
408
409                 public FlagsHandle With (Options options, bool enable)
410                 {
411                         return new FlagsHandle (this, options, enable ? options : 0);
412                 }
413
414                 #region IMemberContext Members
415
416                 public string GetSignatureForError ()
417                 {
418                         return MemberContext.GetSignatureForError ();
419                 }
420
421                 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
422                 {
423                         return MemberContext.LookupExtensionMethod (extensionType, name, arity);
424                 }
425
426                 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
427                 {
428                         return MemberContext.LookupNamespaceOrType (name, arity, mode, loc);
429                 }
430
431                 public FullNamedExpression LookupNamespaceAlias (string name)
432                 {
433                         return MemberContext.LookupNamespaceAlias (name);
434                 }
435
436                 #endregion
437         }
438
439         public class FlowAnalysisContext
440         {
441                 readonly CompilerContext ctx;
442
443                 public FlowAnalysisContext (CompilerContext ctx, ParametersBlock parametersBlock, int definiteAssignmentLength)
444                 {
445                         this.ctx = ctx;
446                         this.ParametersBlock = parametersBlock;
447
448                         DefiniteAssignment = definiteAssignmentLength == 0 ?
449                                 DefiniteAssignmentBitSet.Empty :
450                                 new DefiniteAssignmentBitSet (definiteAssignmentLength);
451                 }
452
453                 public DefiniteAssignmentBitSet DefiniteAssignment { get; set; }
454
455                 public DefiniteAssignmentBitSet DefiniteAssignmentOnTrue { get; set; }
456
457                 public DefiniteAssignmentBitSet DefiniteAssignmentOnFalse { get; set; }
458
459                 public List<LabeledStatement> LabelStack { get; set; }
460
461                 public ParametersBlock ParametersBlock { get; set; }
462
463                 public Report Report {
464                         get {
465                                 return ctx.Report;
466                         }
467                 }
468
469                 public DefiniteAssignmentBitSet SwitchInitialDefinitiveAssignment { get; set; }
470
471                 public TryFinally TryFinally { get; set; }
472
473                 public bool UnreachableReported { get; set; }
474
475                 public DefiniteAssignmentBitSet BranchDefiniteAssignment ()
476                 {
477                         var dat = DefiniteAssignment;
478                         if (dat != DefiniteAssignmentBitSet.Empty)
479                                 DefiniteAssignment = new DefiniteAssignmentBitSet (dat);
480                         return dat;
481                 }
482
483                 public bool IsDefinitelyAssigned (VariableInfo variable)
484                 {
485                         return variable.IsAssigned (DefiniteAssignment);
486                 }
487
488                 public bool IsStructFieldDefinitelyAssigned (VariableInfo variable, string name)
489                 {
490                         return variable.IsStructFieldAssigned (DefiniteAssignment, name);
491                 }
492
493                 public void SetVariableAssigned (VariableInfo variable, bool generatedAssignment = false)
494                 {
495                         variable.SetAssigned (DefiniteAssignment, generatedAssignment);
496                 }
497
498                 public void SetStructFieldAssigned (VariableInfo variable, string name)
499                 {
500                         variable.SetStructFieldAssigned (DefiniteAssignment, name);
501                 }
502         }
503
504
505         //
506         // This class is used during the Statement.Clone operation
507         // to remap objects that have been cloned.
508         //
509         // Since blocks are cloned by Block.Clone, we need a way for
510         // expressions that must reference the block to be cloned
511         // pointing to the new cloned block.
512         //
513         public class CloneContext
514         {
515                 Dictionary<Block, Block> block_map = new Dictionary<Block, Block> ();
516
517                 public void AddBlockMap (Block from, Block to)
518                 {
519                         block_map.Add (from, to);
520                 }
521
522                 public Block LookupBlock (Block from)
523                 {
524                         Block result;
525                         if (!block_map.TryGetValue (from, out result)) {
526                                 result = (Block) from.Clone (this);
527                         }
528
529                         return result;
530                 }
531
532                 ///
533                 /// Remaps block to cloned copy if one exists.
534                 ///
535                 public Block RemapBlockCopy (Block from)
536                 {
537                         Block mapped_to;
538                         if (!block_map.TryGetValue (from, out mapped_to))
539                                 return from;
540
541                         return mapped_to;
542                 }
543         }
544
545         //
546         // Main compiler context
547         //
548         public class CompilerContext
549         {
550                 static readonly TimeReporter DisabledTimeReporter = new TimeReporter (false);
551
552                 readonly Report report;
553                 readonly BuiltinTypes builtin_types;
554                 readonly CompilerSettings settings;
555
556                 Dictionary<string, SourceFile> all_source_files;
557
558                 public CompilerContext (CompilerSettings settings, ReportPrinter reportPrinter)
559                 {
560                         this.settings = settings;
561                         this.report = new Report (this, reportPrinter);
562                         this.builtin_types = new BuiltinTypes ();
563                         this.TimeReporter = DisabledTimeReporter;
564                 }
565
566                 #region Properties
567
568                 public BuiltinTypes BuiltinTypes {
569                         get {
570                                 return builtin_types;
571                         }
572                 }
573
574                 // Used for special handling of runtime dynamic context mostly
575                 // by error reporting but also by member accessibility checks
576                 public bool IsRuntimeBinder {
577                         get; set;
578                 }
579
580                 public Report Report {
581                         get {
582                                 return report;
583                         }
584                 }
585
586                 public CompilerSettings Settings {
587                         get {
588                                 return settings;
589                         }
590                 }
591
592                 public List<SourceFile> SourceFiles {
593                         get {
594                                 return settings.SourceFiles;
595                         }
596                 }
597
598                 internal TimeReporter TimeReporter {
599                         get; set;
600                 }
601
602                 #endregion
603
604                 //
605                 // This is used when we encounter a #line preprocessing directive during parsing
606                 // to register additional source file names
607                 //
608                 public SourceFile LookupFile (CompilationSourceFile comp_unit, string name)
609                 {
610                         if (all_source_files == null) {
611                                 all_source_files = new Dictionary<string, SourceFile> ();
612                                 foreach (var source in SourceFiles)
613                                         all_source_files[source.FullPathName] = source;
614                         }
615
616                         string path;
617                         if (!Path.IsPathRooted (name)) {
618                                 string root = Path.GetDirectoryName (comp_unit.SourceFile.FullPathName);
619                                 path = Path.GetFullPath (Path.Combine (root, name));
620                         } else
621                                 path = name;
622
623                         SourceFile retval;
624                         if (all_source_files.TryGetValue (path, out retval))
625                                 return retval;
626
627                         retval = new SourceFile (name, path, all_source_files.Count + 1);
628                         Location.AddFile (retval);
629                         all_source_files.Add (path, retval);
630                         return retval;
631                 }
632         }
633
634         //
635         // Generic code emitter context
636         //
637         public class BuilderContext
638         {
639                 [Flags]
640                 public enum Options
641                 {
642                         /// <summary>
643                         ///   This flag tracks the `checked' state of the compilation,
644                         ///   it controls whether we should generate code that does overflow
645                         ///   checking, or if we generate code that ignores overflows.
646                         ///
647                         ///   The default setting comes from the command line option to generate
648                         ///   checked or unchecked code plus any source code changes using the
649                         ///   checked/unchecked statements or expressions.   Contrast this with
650                         ///   the ConstantCheckState flag.
651                         /// </summary>
652                         CheckedScope = 1 << 0,
653
654                         AccurateDebugInfo = 1 << 1,
655
656                         OmitDebugInfo = 1 << 2,
657
658                         ConstructorScope = 1 << 3,
659
660                         AsyncBody = 1 << 4
661                 }
662
663                 // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements
664                 // it's public so that we can use a struct at the callsite
665                 public struct FlagsHandle : IDisposable
666                 {
667                         readonly BuilderContext ec;
668                         readonly Options invmask, oldval;
669
670                         public FlagsHandle (BuilderContext ec, Options flagsToSet)
671                                 : this (ec, flagsToSet, flagsToSet)
672                         {
673                         }
674
675                         internal FlagsHandle (BuilderContext ec, Options mask, Options val)
676                         {
677                                 this.ec = ec;
678                                 invmask = ~mask;
679                                 oldval = ec.flags & mask;
680                                 ec.flags = (ec.flags & invmask) | (val & mask);
681                         }
682
683                         public void Dispose ()
684                         {
685                                 ec.flags = (ec.flags & invmask) | oldval;
686                         }
687                 }
688
689                 protected Options flags;
690
691                 public bool HasSet (Options options)
692                 {
693                         return (this.flags & options) == options;
694                 }
695
696                 // Temporarily set all the given flags to the given value.  Should be used in an 'using' statement
697                 public FlagsHandle With (Options options, bool enable)
698                 {
699                         return new FlagsHandle (this, options, enable ? options : 0);
700                 }
701         }
702
703         //
704         // Parser session objects. We could recreate all these objects for each parser
705         // instance but the best parser performance the session object can be reused
706         //
707         public class ParserSession
708         {
709                 MD5 md5;
710
711                 public readonly char[] StreamReaderBuffer = new char[SeekableStreamReader.DefaultReadAheadSize * 2];
712                 public readonly Dictionary<char[], string>[] Identifiers = new Dictionary<char[], string>[Tokenizer.MaxIdentifierLength + 1];
713                 public readonly List<Parameter> ParametersStack = new List<Parameter> (4);
714                 public readonly char[] IDBuilder = new char[Tokenizer.MaxIdentifierLength];
715                 public readonly char[] NumberBuilder = new char[Tokenizer.MaxNumberLength];
716
717                 public LocationsBag LocationsBag { get; set; }
718                 public bool UseJayGlobalArrays { get; set; }
719                 public LocatedToken[] LocatedTokens { get; set; }
720
721                 public MD5 GetChecksumAlgorithm ()
722                 {
723                         return md5 ?? (md5 = MD5.Create ());
724                 }
725         }
726 }