[runtime] Prioritize loading a profiler library from the installation dir over standa...
[mono.git] / mcs / mcs / eval.cs
index 766bb05696b6f9e815d0b80ee621c3e1c54194f7..031da5184551ab74f7987535f2ac436d29894366 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)
                {
@@ -291,6 +298,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>
@@ -341,6 +372,11 @@ namespace Mono.CSharp
                                Console.WriteLine ("Interrupted!\n{0}", e);
                        } finally {
                                invoking = false;
+
+                               if (listener_id != null) {
+                                       ListenerProxy.Unregister (listener_id.Value);
+                                       listener_id = null;
+                               }
                        }
 
                        //
@@ -448,6 +484,11 @@ namespace Mono.CSharp
                        return result;
                }
 
+               /// <summary>
+               /// Experimental!
+               /// </summary>
+               public ValueModificationHandler ModificationListener { get; set; }
+
                enum InputKind {
                        EOF,
                        StatementOrExpression,
@@ -519,7 +560,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;
 
@@ -737,6 +778,7 @@ namespace Mono.CSharp
                        }
                        
                        module.EmitContainer ();
+
                        if (Report.Errors != 0){
                                if (undo != null)
                                        undo.ExecuteUndo ();
@@ -821,13 +863,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 +886,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;
 
@@ -1233,10 +1285,13 @@ namespace Mono.CSharp
                        if (undo_actions == null)
                                undo_actions = new List<Action> ();
 
-                       var existing = current_container.Containers.FirstOrDefault (l => l.Basename == tc.Basename);
-                       if (existing != null) {
-                               current_container.RemoveContainer (existing);
-                               undo_actions.Add (() => current_container.AddTypeContainer (existing));
+                       if (current_container.Containers != null)
+                       {
+                               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));
+                               }
                        }
 
                        undo_actions.Add (() => current_container.RemoveContainer (tc));
@@ -1254,5 +1309,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);
+               }
+       }
 }