Unit Tests for SourceSwitch. Counting the number of events traced based on the Trace...
[mono.git] / mcs / mcs / module.cs
index bcdd786013d11f9cf02e98d302130a2e80b27249..68f1b8ece11b4e0daa90547ebc6d11630b2f9e94 100644 (file)
@@ -36,13 +36,14 @@ namespace Mono.CSharp
                //
                // Compiler generated container for static data
                //
-               sealed class StaticDataContainer : CompilerGeneratedClass
+               sealed class StaticDataContainer : CompilerGeneratedContainer
                {
                        readonly Dictionary<int, Struct> size_types;
-                       new int fields;
+                       int fields;
 
                        public StaticDataContainer (ModuleContainer module)
-                               : base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null), Modifiers.STATIC)
+                               : base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null),
+                                       Modifiers.STATIC | Modifiers.INTERNAL)
                        {
                                size_types = new Dictionary<int, Struct> ();
                        }
@@ -104,6 +105,134 @@ namespace Mono.CSharp
                }
 #endif
 
+               public sealed class PatternMatchingHelper : CompilerGeneratedContainer
+               {
+                       public PatternMatchingHelper (ModuleContainer module)
+                               : base (module, new MemberName ("<PatternMatchingHelper>", Location.Null),
+                                       Modifiers.STATIC | Modifiers.INTERNAL | Modifiers.DEBUGGER_HIDDEN)
+                       {
+                       }
+
+                       public Method NumberMatcher { get; private set; }
+
+                       protected override bool DoDefineMembers ()
+                       {
+                               if (!base.DoDefineMembers ())
+                                       return false;
+
+                               NumberMatcher = GenerateNumberMatcher ();
+                               return true;
+                       }
+
+                       Method GenerateNumberMatcher ()
+                       {
+                               var loc = Location;
+                               var parameters = ParametersCompiled.CreateFullyResolved (
+                                       new [] {
+                                               new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc),
+                                               new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "value", 0, null, loc),
+                                               new Parameter (new TypeExpression (Compiler.BuiltinTypes.Bool, loc), "enumType", 0, null, loc),
+                                       },
+                                       new [] {
+                                               Compiler.BuiltinTypes.Object,
+                                               Compiler.BuiltinTypes.Object,
+                                               Compiler.BuiltinTypes.Bool
+                                       });
+
+                               var m = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Bool, loc),
+                                       Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.DEBUGGER_HIDDEN, new MemberName ("NumberMatcher", loc),
+                                       parameters, null);
+
+                               parameters [0].Resolve (m, 0);
+                               parameters [1].Resolve (m, 1);
+                               parameters [2].Resolve (m, 2);
+
+                               ToplevelBlock top_block = new ToplevelBlock (Compiler, parameters, loc);
+                               m.Block = top_block;
+
+                               //
+                               // if (enumType)
+                               //              return Equals (obj, value);
+                               //
+                               var equals_args = new Arguments (2);
+                               equals_args.Add (new Argument (top_block.GetParameterReference (0, loc)));
+                               equals_args.Add (new Argument (top_block.GetParameterReference (1, loc)));
+
+                               var if_type = new If (
+                                                     top_block.GetParameterReference (2, loc),
+                                                     new Return (new Invocation (new SimpleName ("Equals", loc), equals_args), loc),
+                                                     loc);
+
+                               top_block.AddStatement (if_type);
+
+                               //
+                               // if (obj is Enum || obj == null)
+                               //              return false;
+                               //
+
+                               var if_enum = new If (
+                                                     new Binary (Binary.Operator.LogicalOr,
+                                                             new Is (top_block.GetParameterReference (0, loc), new TypeExpression (Compiler.BuiltinTypes.Enum, loc), loc),
+                                                             new Binary (Binary.Operator.Equality, top_block.GetParameterReference (0, loc), new NullLiteral (loc))),
+                                                     new Return (new BoolLiteral (Compiler.BuiltinTypes, false, loc), loc),
+                                                     loc);
+
+                               top_block.AddStatement (if_enum);
+
+
+                               var system_convert = new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Convert", loc);
+
+                               //
+                               // var converted = System.Convert.ChangeType (obj, System.Convert.GetTypeCode (value));
+                               //
+                               var lv_converted = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Object, top_block, loc);
+
+                               var arguments_gettypecode = new Arguments (1);
+                               arguments_gettypecode.Add (new Argument (top_block.GetParameterReference (1, loc)));
+
+                               var gettypecode = new Invocation (new MemberAccess (system_convert, "GetTypeCode", loc), arguments_gettypecode);
+
+                               var arguments_changetype = new Arguments (1);
+                               arguments_changetype.Add (new Argument (top_block.GetParameterReference (0, loc)));
+                               arguments_changetype.Add (new Argument (gettypecode));
+
+                               var changetype = new Invocation (new MemberAccess (system_convert, "ChangeType", loc), arguments_changetype);
+
+                               top_block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (lv_converted, loc), changetype, loc)));
+
+
+                               //
+                               // return converted.Equals (value)
+                               //
+                               var equals_arguments = new Arguments (1);
+                               equals_arguments.Add (new Argument (top_block.GetParameterReference (1, loc)));
+                               var equals_invocation = new Invocation (new MemberAccess (new LocalVariableReference (lv_converted, loc), "Equals"), equals_arguments);
+                               top_block.AddStatement (new Return (equals_invocation, loc));
+
+                               m.Define ();
+                               m.PrepareEmit ();
+                               AddMember (m);
+
+                               return m;
+                       }
+               }
+
+               PatternMatchingHelper pmh;
+
+               public PatternMatchingHelper CreatePatterMatchingHelper ()
+               {
+                       if (pmh == null) {
+                               pmh = new PatternMatchingHelper (this);
+
+                               pmh.CreateContainer ();
+                               pmh.DefineContainer ();
+                               pmh.Define ();
+                               AddCompilerGeneratedClass (pmh);
+                       }
+
+                       return pmh;
+               }
+
                public CharSet? DefaultCharSet;
                public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
 
@@ -112,6 +241,7 @@ namespace Mono.CSharp
                readonly Dictionary<TypeSpec, PointerContainer> pointer_types;
                readonly Dictionary<TypeSpec, ReferenceContainer> reference_types;
                readonly Dictionary<TypeSpec, MethodSpec> attrs_cache;
+               readonly Dictionary<TypeSpec, AwaiterDefinition> awaiters;
 
                AssemblyDefinition assembly;
                readonly CompilerContext context;
@@ -126,6 +256,9 @@ namespace Mono.CSharp
                PredefinedTypes predefined_types;
                PredefinedMembers predefined_members;
 
+               public Binary.PredefinedOperator[] OperatorsBinaryEqualityLifted;
+               public Binary.PredefinedOperator[] OperatorsBinaryLifted;
+
                static readonly string[] attribute_targets = new string[] { "assembly", "module" };
 
                public ModuleContainer (CompilerContext context)
@@ -143,6 +276,7 @@ namespace Mono.CSharp
                        pointer_types = new Dictionary<TypeSpec, PointerContainer> ();
                        reference_types = new Dictionary<TypeSpec, ReferenceContainer> ();
                        attrs_cache = new Dictionary<TypeSpec, MethodSpec> ();
+                       awaiters = new Dictionary<TypeSpec, AwaiterDefinition> ();
                }
 
                #region Properties
@@ -180,6 +314,8 @@ namespace Mono.CSharp
                        }
                }
 
+               public int CounterAnonymousTypes { get; set; }
+
                public AssemblyDefinition DeclaringAssembly {
                        get {
                                return assembly;
@@ -303,7 +439,7 @@ namespace Mono.CSharp
 
                public override void AddTypeContainer (TypeContainer tc)
                {
-                       containers.Add (tc);
+                       AddTypeContainerMember (tc);
                }
 
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
@@ -392,6 +528,8 @@ namespace Mono.CSharp
                {
                        DefineContainer ();
 
+                       ExpandBaseInterfaces ();
+
                        base.Define ();
 
                        HasTypesFullyDefined = true;
@@ -406,24 +544,30 @@ namespace Mono.CSharp
                        return base.DefineContainer ();
                }
 
+               public void EnableRedefinition ()
+               {
+                       is_defined = false;
+               }
+
                public override void EmitContainer ()
                {
                        if (OptAttributes != null)
                                OptAttributes.Emit ();
 
-                       if (Compiler.Settings.Unsafe) {
+                       if (Compiler.Settings.Unsafe && !assembly.IsSatelliteAssembly) {
                                var pa = PredefinedAttributes.UnverifiableCode;
                                if (pa.IsDefined)
                                        pa.EmitAttribute (builder);
                        }
 
                        foreach (var tc in containers) {
-                               tc.DefineConstants ();
+                               tc.PrepareEmit ();
                        }
 
                        base.EmitContainer ();
 
-                       VerifyMembers ();
+                       if (Compiler.Report.Errors == 0 && !Compiler.Settings.WriteMetadataOnly)
+                               VerifyMembers ();
 
                        if (anonymous_types != null) {
                                foreach (var atypes in anonymous_types)
@@ -458,6 +602,43 @@ namespace Mono.CSharp
                        return null;
                }
 
+               //
+               // Return container with awaiter definition. It never returns null
+               // but all container member can be null for easier error reporting
+               //
+               public AwaiterDefinition GetAwaiter (TypeSpec type)
+               {
+                       AwaiterDefinition awaiter;
+                       if (awaiters.TryGetValue (type, out awaiter))
+                               return awaiter;
+
+                       awaiter = new AwaiterDefinition ();
+
+                       //
+                       // Predefined: bool IsCompleted { get; } 
+                       //
+                       awaiter.IsCompleted = MemberCache.FindMember (type, MemberFilter.Property ("IsCompleted", Compiler.BuiltinTypes.Bool),
+                               BindingRestriction.InstanceOnly) as PropertySpec;
+
+                       //
+                       // Predefined: GetResult ()
+                       //
+                       // The method return type is also result type of await expression
+                       //
+                       awaiter.GetResult = MemberCache.FindMember (type, MemberFilter.Method ("GetResult", 0,
+                               ParametersCompiled.EmptyReadOnlyParameters, null),
+                               BindingRestriction.InstanceOnly) as MethodSpec;
+
+                       //
+                       // Predefined: INotifyCompletion.OnCompleted (System.Action)
+                       //
+                       var nc = PredefinedTypes.INotifyCompletion;
+                       awaiter.INotifyCompletion = !nc.Define () || type.ImplementsInterface (nc.TypeSpec, false);
+
+                       awaiters.Add (type, awaiter);
+                       return awaiter;
+               }
+
                public override void GetCompletionStartingWith (string prefix, List<string> results)
                {
                        var names = Evaluator.GetVarNames ();
@@ -476,11 +657,37 @@ namespace Mono.CSharp
                        return "<module>";
                }
 
+               public Binary.PredefinedOperator[] GetPredefinedEnumAritmeticOperators (TypeSpec enumType, bool nullable)
+               {
+                       TypeSpec underlying;
+                       Binary.Operator mask = 0;
+
+                       if (nullable) {
+                               underlying = Nullable.NullableInfo.GetEnumUnderlyingType (this, enumType);
+                               mask = Binary.Operator.NullableMask;
+                       } else {
+                               underlying = EnumSpec.GetUnderlyingType (enumType);
+                       }
+
+                       var operators = new[] {
+                               new Binary.PredefinedOperator (enumType, underlying,
+                                       mask | Binary.Operator.AdditionMask | Binary.Operator.SubtractionMask | Binary.Operator.DecomposedMask, enumType),
+                               new Binary.PredefinedOperator (underlying, enumType,
+                                       mask | Binary.Operator.AdditionMask | Binary.Operator.SubtractionMask | Binary.Operator.DecomposedMask, enumType),
+                               new Binary.PredefinedOperator (enumType, mask | Binary.Operator.SubtractionMask, underlying)
+                       };
+
+                       return operators;
+               }
+
                public void InitializePredefinedTypes ()
                {
                        predefined_attributes = new PredefinedAttributes (this);
                        predefined_types = new PredefinedTypes (this);
                        predefined_members = new PredefinedMembers (this);
+
+                       OperatorsBinaryEqualityLifted = Binary.CreateEqualityLiftedOperatorsTable (this);
+                       OperatorsBinaryLifted = Binary.CreateStandardLiftedOperatorsTable (this);
                }
 
                public override bool IsClsComplianceRequired ()