Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/context.cs @ 15682

Last change on this file since 15682 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

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