Don't emit reaonly. prefix for reference loads
[mono.git] / mcs / mcs / context.cs
index 534323aa0621d8eebecc602ea0846d66e7012ebe..316968454ef3442f14de3a7f707dd3800ecb805f 100644 (file)
 //
 
 using System;
-using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+
+#if STATIC
+using IKVM.Reflection.Emit;
+#else
 using System.Reflection.Emit;
+#endif
 
 namespace Mono.CSharp
 {
+       public enum LookupMode
+       {
+               Normal = 0,
+               Probing = 1,
+               IgnoreAccessibility = 2
+       }
+
        //
        // Implemented by elements which can act as independent contexts
        // during resolve phase. Used mostly for lookups.
        //
-       public interface IMemberContext
+       public interface IMemberContext : IModuleContext
        {
                //
                // A scope type context, it can be inflated for generic types
                //
-               Type CurrentType { get; }
+               TypeSpec CurrentType { get; }
 
                //
                // A scope type parameters either VAR or MVAR
@@ -32,12 +45,12 @@ namespace Mono.CSharp
                TypeParameter[] CurrentTypeParameters { get; }
 
                //
-               // A type definition of the type context. For partial types definition use
+               // A member definition of the context. For partial types definition use
                // CurrentTypeDefinition.PartialContainer otherwise the context is local
                //
-               // TODO: CurrentType.Definition
+               // TODO: Obsolete it in this context, dynamic context cannot guarantee sensible value
                //
-               TypeContainer CurrentTypeDefinition { get; }
+               MemberCore CurrentMemberDefinition { get; }
 
                bool IsObsolete { get; }
                bool IsUnsafe { get; }
@@ -45,11 +58,16 @@ namespace Mono.CSharp
 
                string GetSignatureForError ();
 
-               ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc);
-               FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104);
+               IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope);
+               FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc);
                FullNamedExpression LookupNamespaceAlias (string name);
        }
 
+       public interface IModuleContext
+       {
+               ModuleContainer Module { get; }
+       }
+
        //
        // Block or statement resolving context
        //
@@ -57,9 +75,7 @@ namespace Mono.CSharp
        {
                FlowBranching current_flow_branching;
 
-               public TypeInferenceContext ReturnTypeInference;
-
-               Type return_type;
+               TypeSpec return_type;
 
                /// <summary>
                ///   The location where return has to jump to return the
@@ -72,7 +88,9 @@ namespace Mono.CSharp
                /// </summary>
                public bool HasReturnLabel;
 
-               public BlockContext (IMemberContext mc, ExplicitBlock block, Type returnType)
+               public int FlowOffset;
+
+               public BlockContext (IMemberContext mc, ExplicitBlock block, TypeSpec returnType)
                        : base (mc)
                {
                        if (returnType == null)
@@ -84,6 +102,16 @@ namespace Mono.CSharp
                        CurrentBlock = block;
                }
 
+               public BlockContext (ResolveContext rc, ExplicitBlock block, TypeSpec returnType)
+                       : this (rc.MemberContext, block, returnType)
+               {
+                       if (rc.IsUnsafe)
+                               flags |= ResolveContext.Options.UnsafeScope;
+
+                       if (rc.HasSet (ResolveContext.Options.CheckedScope))
+                               flags |= ResolveContext.Options.CheckedScope;
+               }
+
                public override FlowBranching CurrentBranching {
                        get { return current_flow_branching; }
                }
@@ -131,14 +159,14 @@ namespace Mono.CSharp
                        return branching;
                }
 
-               public FlowBranchingIterator StartFlowBranching (Iterator iterator)
+               public FlowBranchingIterator StartFlowBranching (StateMachineInitializer iterator, FlowBranching parent)
                {
-                       FlowBranchingIterator branching = new FlowBranchingIterator (CurrentBranching, iterator);
+                       FlowBranchingIterator branching = new FlowBranchingIterator (parent, iterator);
                        current_flow_branching = branching;
                        return branching;
                }
 
-               public FlowBranchingToplevel StartFlowBranching (ToplevelBlock stmt, FlowBranching parent)
+               public FlowBranchingToplevel StartFlowBranching (ParametersBlock stmt, FlowBranching parent)
                {
                        FlowBranchingToplevel branching = new FlowBranchingToplevel (parent, stmt);
                        current_flow_branching = branching;
@@ -178,7 +206,7 @@ namespace Mono.CSharp
                                HasReturnLabel = true;
                }
 
-               public Type ReturnType {
+               public TypeSpec ReturnType {
                        get { return return_type; }
                }
        }
@@ -237,6 +265,10 @@ namespace Mono.CSharp
 
                        ConstructorScope = 1 << 11,
 
+                       UsingInitializerScope = 1 << 12,
+
+                       LockScope = 1 << 13,
+
                        /// <summary>
                        ///   Whether control flow analysis is enabled
                        /// </summary>
@@ -260,7 +292,11 @@ namespace Mono.CSharp
                        //
                        InferReturnType = 1 << 23,
 
-                       OmitDebuggingInfo = 1 << 24
+                       OmitDebuggingInfo = 1 << 24,
+
+                       ExpressionTreeConversion = 1 << 25,
+
+                       InvokeSpecialName = 1 << 26
                }
 
                // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements
@@ -282,20 +318,20 @@ namespace Mono.CSharp
                                oldval = ec.flags & mask;
                                ec.flags = (ec.flags & invmask) | (val & mask);
 
-                               if ((mask & Options.ProbingMode) != 0)
-                                       Report.DisableReporting ();
+//                             if ((mask & Options.ProbingMode) != 0)
+//                                     ec.Report.DisableReporting ();
                        }
 
                        public void Dispose ()
                        {
-                               if ((invmask & Options.ProbingMode) == 0)
-                                       Report.EnableReporting ();
+//                             if ((invmask & Options.ProbingMode) == 0)
+//                                     ec.Report.EnableReporting ();
 
                                ec.flags = (ec.flags & invmask) | oldval;
                        }
                }
 
-               Options flags;
+               protected Options flags;
 
                //
                // Whether we are inside an anonymous method.
@@ -309,7 +345,7 @@ namespace Mono.CSharp
 
                public Block CurrentBlock;
 
-               public IMemberContext MemberContext;
+               public readonly IMemberContext MemberContext;
 
                /// <summary>
                ///   If this is non-null, points to the current switch statement
@@ -318,12 +354,15 @@ namespace Mono.CSharp
 
                public ResolveContext (IMemberContext mc)
                {
+                       if (mc == null)
+                               throw new ArgumentNullException ();
+
                        MemberContext = mc;
 
                        //
                        // The default setting comes from the command line option
                        //
-                       if (RootContext.Checked)
+                       if (mc.Module.Compiler.Settings.Checked)
                                flags |= Options.CheckedScope;
 
                        //
@@ -338,6 +377,20 @@ namespace Mono.CSharp
                        flags |= options;
                }
 
+               #region Properties
+
+               public BuiltinTypes BuiltinTypes {
+                       get {
+                               return MemberContext.Module.Compiler.BuiltinTypes;
+                       }
+               }
+
+               public virtual ExplicitBlock ConstructorBlock {
+                       get {
+                               return CurrentBlock.Explicit;
+                       }
+               }
+
                public virtual FlowBranching CurrentBranching {
                        get { return null; }
                }
@@ -349,7 +402,7 @@ namespace Mono.CSharp
                        get { return CurrentAnonymousMethod as Iterator; }
                }
 
-               public Type CurrentType {
+               public TypeSpec CurrentType {
                        get { return MemberContext.CurrentType; }
                }
 
@@ -357,8 +410,8 @@ namespace Mono.CSharp
                        get { return MemberContext.CurrentTypeParameters; }
                }
 
-               public TypeContainer CurrentTypeDefinition {
-                       get { return MemberContext.CurrentTypeDefinition; }
+               public MemberCore CurrentMemberDefinition {
+                       get { return MemberContext.CurrentMemberDefinition; }
                }
 
                public bool ConstantCheckState {
@@ -370,7 +423,34 @@ namespace Mono.CSharp
                }
 
                public bool IsInProbingMode {
-                       get { return (flags & Options.ProbingMode) != 0; }
+                       get {
+                               return (flags & Options.ProbingMode) != 0;
+                       }
+               }
+
+               public bool IsObsolete {
+                       get {
+                               // Disables obsolete checks when probing is on
+                               return MemberContext.IsObsolete;
+                       }
+               }
+
+               public bool IsStatic {
+                       get {
+                               return MemberContext.IsStatic;
+                       }
+               }
+
+               public bool IsUnsafe {
+                       get {
+                               return HasSet (Options.UnsafeScope) || MemberContext.IsUnsafe;
+                       }
+               }
+
+               public bool IsRuntimeBinder {
+                       get {
+                               return Module.Compiler.IsRuntimeBinder;
+                       }
                }
 
                public bool IsVariableCapturingRequired {
@@ -379,26 +459,25 @@ namespace Mono.CSharp
                        }
                }
 
+               public ModuleContainer Module {
+                       get {
+                               return MemberContext.Module;
+                       }
+               }
+
                public bool OmitStructFlowAnalysis {
                        get { return (flags & Options.OmitStructFlowAnalysis) != 0; }
                }
 
-               // TODO: Merge with CompilerGeneratedThis
-               public Expression GetThis (Location loc)
-               {
-                       This my_this;
-                       if (CurrentBlock != null)
-                               my_this = new This (CurrentBlock, loc);
-                       else
-                               my_this = new This (loc);
-
-                       if (!my_this.ResolveBase (this))
-                               my_this = null;
-
-                       return my_this;
+               public Report Report {
+                       get {
+                               return Module.Compiler.Report;
+                       }
                }
 
-               public bool MustCaptureVariable (LocalInfo local)
+               #endregion
+
+               public bool MustCaptureVariable (INamedBlockVariable local)
                {
                        if (CurrentAnonymousMethod == null)
                                return false;
@@ -408,7 +487,7 @@ namespace Mono.CSharp
                        if (CurrentAnonymousMethod.IsIterator)
                                return true;
 
-                       return local.Block.Toplevel != CurrentBlock.Toplevel;
+                       return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original;
                }
 
                public bool HasSet (Options options)
@@ -421,6 +500,7 @@ namespace Mono.CSharp
                        return (this.flags & options) != 0;
                }
 
+
                // Temporarily set all the given flags to the given value.  Should be used in an 'using' statement
                public FlagsHandle Set (Options options)
                {
@@ -432,14 +512,6 @@ namespace Mono.CSharp
                        return new FlagsHandle (this, options, enable ? options : 0);
                }
 
-               public FlagsHandle WithFlowAnalysis (bool do_flow_analysis, bool omit_struct_analysis)
-               {
-                       Options newflags =
-                               (do_flow_analysis ? Options.DoFlowAnalysis : 0) |
-                               (omit_struct_analysis ? Options.OmitStructFlowAnalysis : 0);
-                       return new FlagsHandle (this, Options.DoFlowAnalysis | Options.OmitStructFlowAnalysis, newflags);
-               }
-
                #region IMemberContext Members
 
                public string GetSignatureForError ()
@@ -447,29 +519,14 @@ namespace Mono.CSharp
                        return MemberContext.GetSignatureForError ();
                }
 
-               public bool IsObsolete {
-                       get {
-                               // Disables obsolete checks when probing is on
-                               return IsInProbingMode || MemberContext.IsObsolete;
-                       }
-               }
-
-               public bool IsStatic {
-                       get { return MemberContext.IsStatic; }
-               }
-
-               public bool IsUnsafe {
-                       get { return HasSet (Options.UnsafeScope) || MemberContext.IsUnsafe; }
-               }
-
-               public ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
+               public IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope)
                {
-                       return MemberContext.LookupExtensionMethod (extensionType, name, loc);
+                       return MemberContext.LookupExtensionMethod (extensionType, name, arity, ref scope);
                }
 
-               public FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
+               public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
                {
-                       return MemberContext.LookupNamespaceOrType (name, loc, ignore_cs0104);
+                       return MemberContext.LookupNamespaceOrType (name, arity, mode, loc);
                }
 
                public FullNamedExpression LookupNamespaceAlias (string name)
@@ -490,23 +547,18 @@ namespace Mono.CSharp
        //
        public class CloneContext
        {
-               Hashtable block_map = new Hashtable ();
-               Hashtable variable_map;
+               Dictionary<Block, Block> block_map = new Dictionary<Block, Block> ();
 
                public void AddBlockMap (Block from, Block to)
                {
-                       if (block_map.Contains (from))
-                               return;
-                       block_map[from] = to;
+                       block_map.Add (from, to);
                }
 
                public Block LookupBlock (Block from)
                {
-                       Block result = (Block) block_map[from];
-
-                       if (result == null) {
+                       Block result;
+                       if (!block_map.TryGetValue (from, out result)) {
                                result = (Block) from.Clone (this);
-                               block_map[from] = result;
                        }
 
                        return result;
@@ -517,31 +569,173 @@ namespace Mono.CSharp
                ///
                public Block RemapBlockCopy (Block from)
                {
-                       Block mapped_to = (Block) block_map[from];
-                       if (mapped_to == null)
+                       Block mapped_to;
+                       if (!block_map.TryGetValue (from, out mapped_to))
                                return from;
 
                        return mapped_to;
                }
+       }
 
-               public void AddVariableMap (LocalInfo from, LocalInfo to)
+       //
+       // Main compiler context
+       //
+       public class CompilerContext
+       {
+               static readonly TimeReporter DisabledTimeReporter = new TimeReporter (false);
+
+               readonly Report report;
+               readonly BuiltinTypes builtin_types;
+               readonly CompilerSettings settings;
+
+               Dictionary<string, SourceFile> all_source_files;
+
+               public CompilerContext (CompilerSettings settings, Report report)
                {
-                       if (variable_map == null)
-                               variable_map = new Hashtable ();
+                       this.settings = settings;
+                       this.report = report;
+                       this.builtin_types = new BuiltinTypes ();
+                       this.TimeReporter = DisabledTimeReporter;
+               }
+
+               #region Properties
 
-                       if (variable_map.Contains (from))
-                               return;
-                       variable_map[from] = to;
+               public BuiltinTypes BuiltinTypes {
+                       get {
+                               return builtin_types;
+                       }
                }
 
-               public LocalInfo LookupVariable (LocalInfo from)
+               // Used for special handling of runtime dynamic context mostly
+               // by error reporting but also by member accessibility checks
+               public bool IsRuntimeBinder {
+                       get; set;
+               }
+
+               public Report Report {
+                       get {
+                               return report;
+                       }
+               }
+
+               public CompilerSettings Settings {
+                       get {
+                               return settings;
+                       }
+               }
+
+               public List<CompilationSourceFile> SourceFiles {
+                       get {
+                               return settings.SourceFiles;
+                       }
+               }
+
+               internal TimeReporter TimeReporter {
+                       get; set;
+               }
+
+               #endregion
+
+               //
+               // This is used when we encounter a #line preprocessing directive during parsing
+               // to register additional source file names
+               //
+               public SourceFile LookupFile (CompilationSourceFile comp_unit, string name)
                {
-                       LocalInfo result = (LocalInfo) variable_map[from];
+                       if (all_source_files == null) {
+                               all_source_files = new Dictionary<string, SourceFile> ();
+                               foreach (var source in SourceFiles)
+                                       all_source_files[source.FullPathName] = source;
+                       }
 
-                       if (result == null)
-                               throw new Exception ("LookupVariable: looking up a variable that has not been registered yet");
+                       string path;
+                       if (!Path.IsPathRooted (name)) {
+                               string root = Path.GetDirectoryName (comp_unit.FullPathName);
+                               path = Path.Combine (root, name);
+                       } else
+                               path = name;
 
-                       return result;
+                       SourceFile retval;
+                       if (all_source_files.TryGetValue (path, out retval))
+                               return retval;
+
+                       retval = Location.AddFile (name, path);
+                       all_source_files.Add (path, retval);
+                       return retval;
+               }
+       }
+
+       //
+       // Generic code emitter context
+       //
+       public class BuilderContext
+       {
+               [Flags]
+               public enum Options
+               {
+                       /// <summary>
+                       ///   This flag tracks the `checked' state of the compilation,
+                       ///   it controls whether we should generate code that does overflow
+                       ///   checking, or if we generate code that ignores overflows.
+                       ///
+                       ///   The default setting comes from the command line option to generate
+                       ///   checked or unchecked code plus any source code changes using the
+                       ///   checked/unchecked statements or expressions.   Contrast this with
+                       ///   the ConstantCheckState flag.
+                       /// </summary>
+                       CheckedScope = 1 << 0,
+
+                       /// <summary>
+                       ///   The constant check state is always set to `true' and cant be changed
+                       ///   from the command line.  The source code can change this setting with
+                       ///   the `checked' and `unchecked' statements and expressions. 
+                       /// </summary>
+                       ConstantCheckState = 1 << 1,
+
+                       AllCheckStateFlags = CheckedScope | ConstantCheckState,
+
+                       OmitDebugInfo = 1 << 2,
+
+                       ConstructorScope = 1 << 3
+               }
+
+               // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements
+               // it's public so that we can use a struct at the callsite
+               public struct FlagsHandle : IDisposable
+               {
+                       BuilderContext ec;
+                       readonly Options invmask, oldval;
+
+                       public FlagsHandle (BuilderContext ec, Options flagsToSet)
+                               : this (ec, flagsToSet, flagsToSet)
+                       {
+                       }
+
+                       internal FlagsHandle (BuilderContext ec, Options mask, Options val)
+                       {
+                               this.ec = ec;
+                               invmask = ~mask;
+                               oldval = ec.flags & mask;
+                               ec.flags = (ec.flags & invmask) | (val & mask);
+                       }
+
+                       public void Dispose ()
+                       {
+                               ec.flags = (ec.flags & invmask) | oldval;
+                       }
+               }
+
+               Options flags;
+
+               public bool HasSet (Options options)
+               {
+                       return (this.flags & options) == options;
+               }
+
+               // Temporarily set all the given flags to the given value.  Should be used in an 'using' statement
+               public FlagsHandle With (Options options, bool enable)
+               {
+                       return new FlagsHandle (this, options, enable ? options : 0);
                }
        }
-}
\ No newline at end of file
+}