Fixes for bug#54388 "InternalsVisibleTo is case sensitive" * Fix the JIT so that...
[mono.git] / mcs / mcs / eval.cs
index 5d9a291b1c51f1c3bc99b1dbfa36b37530c8202f..d4e83a506a0fcfbf1d1b00d8522173ca92f15462 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;
+                               }
                        }
 
                        //
@@ -370,26 +416,30 @@ namespace Mono.CSharp
                                if (parser == null){
                                        return null;
                                }
-                               
-                               Class parser_result = parser.InteractiveResult;
 
-#if NET_4_0
+                               Class host = parser.InteractiveResult;
+
+                               var base_class_imported = importer.ImportType (base_class);
+                               var baseclass_list = new List<FullNamedExpression> (1) {
+                                       new TypeExpression (base_class_imported, host.Location)
+                               };
+                               host.SetBaseTypes (baseclass_list);
+
                                var access = AssemblyBuilderAccess.RunAndCollect;
-#else
-                               var access = AssemblyBuilderAccess.Run;
-#endif
                                var a = new AssemblyDefinitionDynamic (module, "completions");
                                a.Create (AppDomain.CurrentDomain, access);
                                module.SetDeclaringAssembly (a);
 
                                // Need to setup MemberCache
-                               parser_result.CreateContainer ();
+                               host.CreateContainer ();
+                               // Need to setup base type
+                               host.DefineContainer ();
 
-                               var method = parser_result.Members[0] as Method;
+                               var method = host.Members[0] as Method;
                                BlockContext bc = new BlockContext (method, method.Block, ctx.BuiltinTypes.Void);
 
                                try {
-                                       method.Block.Resolve (null, bc, method);
+                                       method.Block.Resolve (bc, method);
                                } catch (CompletionResult cr) {
                                        prefix = cr.BaseText;
                                        return cr.Result;
@@ -440,6 +490,11 @@ namespace Mono.CSharp
                        return result;
                }
 
+               /// <summary>
+               /// Experimental!
+               /// </summary>
+               public ValueModificationHandler ModificationListener { get; set; }
+
                enum InputKind {
                        EOF,
                        StatementOrExpression,
@@ -459,7 +514,7 @@ namespace Mono.CSharp
                //
                InputKind ToplevelOrStatement (SeekableStreamReader seekable)
                {
-                       Tokenizer tokenizer = new Tokenizer (seekable, source_file, new ParserSession ());
+                       Tokenizer tokenizer = new Tokenizer (seekable, source_file, new ParserSession (), ctx.Report);
                        
                        // Prefer contextual block keywords over identifiers
                        tokenizer.parsing_block++;
@@ -472,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:
@@ -511,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;
 
@@ -644,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);
                        }
 
@@ -729,6 +781,7 @@ namespace Mono.CSharp
                        }
                        
                        module.EmitContainer ();
+
                        if (Report.Errors != 0){
                                if (undo != null)
                                        undo.ExecuteUndo ();
@@ -813,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);
                        }
 
@@ -830,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;
 
@@ -1038,9 +1101,7 @@ namespace Mono.CSharp
                static public string help {
                        get {
                                return "Static methods:\n" +
-#if !NET_2_1
                                        "  Describe (object);       - Describes the object's type\n" +
-#endif
                                        "  LoadPackage (package);   - Loads the given Package (like -pkg:FILE)\n" +
                                        "  LoadAssembly (assembly); - Loads the given assembly (like -r:ASSEMBLY)\n" +
                                        "  ShowVars ();             - Shows defined local variables.\n" +
@@ -1073,7 +1134,7 @@ namespace Mono.CSharp
                        QuitRequested = true;
                }
 
-#if !NET_2_1
+#if !MOBILE
                /// <summary>
                ///   Describes an object or a type.
                /// </summary>
@@ -1227,10 +1288,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));
@@ -1248,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);
+               }
+       }
 }