Remove Thread.[Abort|Suspend|Resume] from TvOS/WatchOS.
[mono.git] / mcs / mcs / eval.cs
index 5bda997062587af84c2d227d0cf5e371c5dea3ef..62c02b1fd5602de8f4a01d5096f183472d3d2b9a 100644 (file)
@@ -24,6 +24,11 @@ using System.Linq;
 namespace Mono.CSharp
 {
 
+       /// <summary>
+       /// Experimental!
+       /// </summary>
+       public delegate void ValueModificationHandler (string variableName, int row, int column, object value);
+
        /// <summary>
        ///   Evaluator: provides an API to evaluate C# statements and
        ///   expressions dynamically.
@@ -71,6 +76,8 @@ namespace Mono.CSharp
                readonly ModuleContainer module;
                readonly ReflectionImporter importer;
                readonly CompilationSourceFile source_file;
+
+               int? listener_id;
                
                public Evaluator (CompilerContext ctx)
                {
@@ -185,8 +192,13 @@ namespace Mono.CSharp
                        if (!inited || !invoking)
                                return;
                        
-                       if (invoke_thread != null)
+                       if (invoke_thread != null) {
+#if MONO_FEATURE_THREAD_ABORT
                                invoke_thread.Abort ();
+#else
+                               invoke_thread.Interrupt ();
+#endif
+                       }
                }
 
                /// <summary>
@@ -291,6 +303,30 @@ namespace Mono.CSharp
                        return compiled;
                }
 
+               static MethodInfo listener_proxy_value;
+               internal void EmitValueChangedCallback (EmitContext ec, string name, TypeSpec type, Location loc)
+               {
+                       if (listener_id == null)
+                               listener_id = ListenerProxy.Register (ModificationListener);
+
+                       if (listener_proxy_value == null)
+                               listener_proxy_value = typeof (ListenerProxy).GetMethod ("ValueChanged");
+
+#if STATIC
+                       throw new NotSupportedException ();
+#else
+                       // object value, int row, int col, string name, int listenerId
+                       if (type.IsStructOrEnum)
+                               ec.Emit (OpCodes.Box, type);
+
+                       ec.EmitInt (loc.Row);
+                       ec.EmitInt (loc.Column);
+                       ec.Emit (OpCodes.Ldstr, name);
+                       ec.EmitInt (listener_id.Value);
+                       ec.Emit (OpCodes.Call, listener_proxy_value);
+#endif
+               }
+
                /// <summary>
                ///   Evaluates and expression or statement and returns any result values.
                /// </summary>
@@ -336,11 +372,21 @@ namespace Mono.CSharp
                                invoke_thread = System.Threading.Thread.CurrentThread;
                                invoking = true;
                                compiled (ref retval);
+#if MONO_FEATURE_THREAD_ABORT
                        } catch (ThreadAbortException e){
                                Thread.ResetAbort ();
                                Console.WriteLine ("Interrupted!\n{0}", e);
+#else
+                       } catch (ThreadInterruptedException e) {
+                               Console.WriteLine ("Interrupted!\n{0}", e);
+#endif
                        } finally {
                                invoking = false;
+
+                               if (listener_id != null) {
+                                       ListenerProxy.Unregister (listener_id.Value);
+                                       listener_id = null;
+                               }
                        }
 
                        //
@@ -379,11 +425,7 @@ namespace Mono.CSharp
                                };
                                host.SetBaseTypes (baseclass_list);
 
-#if NET_4_0
                                var access = AssemblyBuilderAccess.RunAndCollect;
-#else
-                               var access = AssemblyBuilderAccess.Run;
-#endif
                                var a = new AssemblyDefinitionDynamic (module, "completions");
                                a.Create (AppDomain.CurrentDomain, access);
                                module.SetDeclaringAssembly (a);
@@ -448,6 +490,11 @@ namespace Mono.CSharp
                        return result;
                }
 
+               /// <summary>
+               /// Experimental!
+               /// </summary>
+               public ValueModificationHandler ModificationListener { get; set; }
+
                enum InputKind {
                        EOF,
                        StatementOrExpression,
@@ -480,6 +527,7 @@ namespace Mono.CSharp
                        // These are toplevels
                        case Token.EXTERN:
                        case Token.OPEN_BRACKET:
+                       case Token.OPEN_BRACKET_EXPR:
                        case Token.ABSTRACT:
                        case Token.CLASS:
                        case Token.ENUM:
@@ -519,7 +567,7 @@ namespace Mono.CSharp
                                if (t == Token.EOF)
                                        return InputKind.EOF;
 
-                               if (t == Token.IDENTIFIER)
+                               if (t == Token.IDENTIFIER || t == Token.STATIC)
                                        return InputKind.CompilationUnit;
                                return InputKind.StatementOrExpression;
 
@@ -652,11 +700,7 @@ namespace Mono.CSharp
                                assembly = new AssemblyDefinitionDynamic (module, current_debug_name, current_debug_name);
                                assembly.Importer = importer;
                        } else {
-#if NET_4_0
                                access = AssemblyBuilderAccess.RunAndCollect;
-#else
-                               access = AssemblyBuilderAccess.Run;
-#endif
                                assembly = new AssemblyDefinitionDynamic (module, current_debug_name);
                        }
 
@@ -737,6 +781,7 @@ namespace Mono.CSharp
                        }
                        
                        module.EmitContainer ();
+
                        if (Report.Errors != 0){
                                if (undo != null)
                                        undo.ExecuteUndo ();
@@ -821,13 +866,19 @@ namespace Mono.CSharp
 
                public string GetUsing ()
                {
+                       if (source_file == null || source_file.Usings == null)
+                               return string.Empty;
+
                        StringBuilder sb = new StringBuilder ();
                        // TODO:
                        //foreach (object x in ns.using_alias_list)
                        //    sb.AppendFormat ("using {0};\n", x);
 
                        foreach (var ue in source_file.Usings) {
-                               sb.AppendFormat ("using {0};", ue.ToString ());
+                               if (ue.Alias != null || ue.ResolvedExpression == null)
+                                       continue;
+
+                               sb.AppendFormat("using {0};", ue.ToString ());
                                sb.Append (Environment.NewLine);
                        }
 
@@ -838,7 +889,11 @@ namespace Mono.CSharp
                {
                        var res = new List<string> ();
 
-                       foreach (var ue in source_file.Usings) {
+                       if (source_file == null || source_file.Usings == null)
+                               return res;
+
+                       foreach (var ue in source_file.Usings)
+                       {
                                if (ue.Alias != null || ue.ResolvedExpression == null)
                                        continue;
 
@@ -1235,7 +1290,7 @@ namespace Mono.CSharp
 
                        if (current_container.Containers != null)
                        {
-                               var existing = current_container.Containers.FirstOrDefault (l => l.Basename == tc.Basename);
+                               var existing = current_container.Containers.FirstOrDefault (l => l.MemberName.Basename == tc.MemberName.Basename);
                                if (existing != null) {
                                        current_container.RemoveContainer (existing);
                                        undo_actions.Add (() => current_container.AddTypeContainer (existing));
@@ -1257,5 +1312,38 @@ namespace Mono.CSharp
                        undo_actions = null;
                }
        }
-       
+
+       static class ListenerProxy
+       {
+               static readonly Dictionary<int, ValueModificationHandler> listeners = new Dictionary<int, ValueModificationHandler> ();
+
+               static int counter;
+
+               public static int Register (ValueModificationHandler listener)
+               {
+                       lock (listeners) {
+                               var id = counter++;
+                               listeners.Add (id, listener);
+                               return id;
+                       }
+               }
+
+               public static void Unregister (int listenerId)
+               {
+                       lock (listeners) {
+                               listeners.Remove (listenerId);
+                       }
+               }
+
+               public static void ValueChanged (object value, int row, int col, string name, int listenerId)
+               {
+                       ValueModificationHandler action;
+                       lock (listeners) {
+                               if (!listeners.TryGetValue (listenerId, out action))
+                                       return;
+                       }
+
+                       action (name, row, col, value);
+               }
+       }
 }