Work to support typing compilation-unit level declarations in the shell.
authorMiguel de Icaza <miguel@gnome.org>
Sat, 30 Aug 2008 20:14:13 +0000 (20:14 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Sat, 30 Aug 2008 20:14:13 +0000 (20:14 -0000)
There is a major problem with it though: Reflection keeps gettting data
confused if you are using any of the *Builder classes and ends up
referencing other classes.     This seems like a real bug in Emit, not
really just an intended side effect.

So until all of those issues are fixed, the code path is disabled, but
at least declaring types works now.

svn path=/trunk/mcs/; revision=111974

14 files changed:
mcs/mcs/ChangeLog
mcs/mcs/Makefile
mcs/mcs/anonymous.cs
mcs/mcs/class.cs
mcs/mcs/cs-parser.jay
mcs/mcs/cs-tokenizer.cs
mcs/mcs/decl.cs
mcs/mcs/driver.cs
mcs/mcs/getline.cs
mcs/mcs/namespace.cs
mcs/mcs/repl.cs
mcs/mcs/repl.txt
mcs/mcs/rootcontext.cs
mcs/mcs/roottypes.cs

index 34b09d30ada6153d7088c7c91b733fc09fe058ff..abbbdce01f26f0fe8d9753d2b1a9f2299a7a382b 100644 (file)
@@ -1,3 +1,73 @@
+2008-08-30  Miguel de Icaza  <miguel@novell.com>
+
+       * namespace.cs (LookupType): In EvalMode, try to replace
+       the TypeBuilder from our cache with a Type as Reflection.Emit does
+       not  like to mix code from older assemblies emitted and new
+       assemblies emitted. 
+
+       This sounds like a serious Mono bug that prevents multiple
+       assemblies to be generated and consumed at the same time.
+
+       * cs-parser.jay (push_current_class): Do not make interactive
+       classes internal or private, make them public as we currently
+       generate each new class in a new assembly.   
+
+2008-08-29  Miguel de Icaza  <miguel@novell.com>
+
+       * decl.cs, roottypes.cs, class.cs:: Add an infrastructure to
+       remove types that are entered into the global namespace during
+       parsing so that we can remove them on failure.
+       * cs-parser.jay: Parsing: we now keep track of types that are
+       entered into global variables and queue those in case the parsing
+       or resolution fail.
+       This happens in a few situations: during partial-input, we invoke
+       the parser repeatedly for example with the string "class X", this
+       would cause X to be registed, and we need to remove this
+       registration so that another parse attempt later with say "class X {"
+       would actually work.
+       Additionally, if there is an error in the resolution phase, for
+       example: "class X : NonExistant {}" th
+       
+       * cs-parser.jay: Be more precise with the errors being raised,
+       instead of flagging all exceptions during parsing to be attributed
+       to the parsing process, distinguish those from errors happening in
+       the actions and hint that using -v would produce the actual
+       exception. 
+
+       * repl.cs: Do not load all compiler references on each reset,
+       doing the partial reset takes care of this.
+       
+2008-08-28  Miguel de Icaza  <miguel@novell.com>
+
+       * repl.cs: Add support for loading all the files from
+       ~/.config/csharp/*cs as startup scripts and ~/.config/csharp/*.dll
+       as shell libraries.
+
+       Introduce a micro-parser that is able to deambiguate on its input
+       whether we are dealing with a compilation unit (namespace, class,
+       interface, struct, delegate) declaration or a statement.   This
+       allows both declarations and statements to be entered. 
+
+       Set history size by default to 300 lines.
+
+       Instead of distinguishing based on the parser.InteractiveResult,
+       have only two cases: statements were parsed, or a compilation unit
+       was.   Always pull the Using statement additions from the
+       compilation unit parse.
+       
+       * cs-tokenizer.cs: Rename tokens to better describe their intent
+       (EvalStatementParserCharacter and EvalCompilationUnitParserCharacter).
+       
+       * rootcontext.cs: Split EvalMode into EvalMode and StatementMode.
+       EvalMode is used to trigger the lookup of global variables while
+       StatementMode is used turn variable declarations into static
+       fields.
+
+       * getline.cs: Allow history size to be set.
+       
 2008-08-29  Marek Safar  <marek.safar@gmail.com>
 
        A fix for bug #360755
index 0e44e7765f57fb2565aec5ac549b1197458ca1fb..a4712e1fa7fa1087b0d4c829c91774ad3b3bdaac 100644 (file)
@@ -134,12 +134,11 @@ profile : $(PROGRAM)
 # Update manually.
 qh:
        MONO_PATH="../class/lib/net_2_0$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH" $(RUNTIME) $(RUNTIME_FLAGS) ../class/lib/net_2_0/gmcs.exe  /codepage:65001 -d:GMCS_SOURCE  -d:NET_1_1 -d:NET_2_0 -debug -target:exe -out:gmcs.exe cs-parser.cs  @gmcs.exe.sources  
-       @ cp $(COMPILER_NAME).exe* $(topdir)/class/lib/$(PROFILE)/
 
 q: cs-parser.cs qh
        echo 'System.Console.WriteLine ("Hello");' | mono --debug gmcs.exe -v --shell
        echo -e 'using System;\nConsole.WriteLine ("hello");' | mono --debug gmcs.exe -v --shell
-       echo -e '"foo" == "bar"' | mono --debug gmcs.exe -v --shell
+       echo -e '"foo" == "bar";' | mono --debug gmcs.exe -v --shell
        echo -e 'var a = 1;\na + 2;' | mono --debug gmcs.exe -v --shell
        echo -e 'int j;\nj = 1;' | mono --debug gmcs.exe -v --shell
 
index 5db9f35dbbdc341bd679f9ac17912c4f0c04b0f6..80cc270e8565eb9fc4be9ea57f5ee7fcf72a7017 100644 (file)
@@ -1686,6 +1686,11 @@ namespace Mono.CSharp {
                        return false;
                }
 
+               protected override void RemoveFromContainer (string name)
+               {
+                       defined_names.Remove (name);
+               }
+
                void DefineOverrides ()
                {
                        Location loc = Location;
index d32d2c780f5c9004e40a0d9075176ccf716e400d..72b6663d87455ecc01fcd4a4af9adbc67c776d41 100644 (file)
@@ -299,6 +299,11 @@ namespace Mono.CSharp {
                        return AddToContainer (ds, ds.Basename);
                }
 
+               protected virtual void RemoveMemberType (DeclSpace ds)
+               {
+                       RemoveFromContainer (ds.Basename);
+               }
+
                public void AddConstant (Const constant)
                {
                        if (!AddMember (constant))
@@ -380,6 +385,13 @@ namespace Mono.CSharp {
                        return tc;
                }
 
+               public virtual void RemoveTypeContainer (TypeContainer next_part)
+               {
+                       if (types != null)
+                               types.Remove (next_part);
+                       RemoveMemberType (next_part);
+               }
+               
                public void AddDelegate (Delegate d)
                {
                        if (!AddMemberType (d))
index 3b2bbbc650ecdb3082e96979d1a1418fcfa9186f..84a2f5b3d13c87047b4a607a157af2ae11ea53b6 100644 (file)
@@ -127,6 +127,12 @@ namespace Mono.CSharp
                /// resulting expression
                public object InteractiveResult;
 
+               //
+               // Keeps track of global data changes to undo on parser error
+               //
+               public Undo undo;
+
+               // A counter to create new class names in interactive mode
                static int class_count;
 %}
 
@@ -316,9 +322,10 @@ namespace Mono.CSharp
 %token GENERIC_DIMENSION
 %token DEFAULT_COLON
 
-// Make the parser go into interactive parsing
-%token INTERACTIVE_PARSER
-%token INTERACTIVE_PARSER_USING_DIRECTIVES
+// Make the parser go into eval mode parsing (statements and compilation units).
+%token EVAL_STATEMENT_PARSER
+%token EVAL_COMPILATION_UNIT_PARSER
+%token EVAL_USING_DECLARATIONS_UNIT_PARSER
 
 /* Add precedence rules to solve dangling else s/r conflict */
 %nonassoc LOWPREC
@@ -2420,8 +2427,11 @@ enum_declaration
 
                        e.AddEnumMember (em);
                }
+               if (RootContext.EvalMode)
+                       undo.AddTypeContainer (current_container, e);
 
                current_container.AddTypeContainer (e);
+
                $$ = e;
 
          }
@@ -5416,11 +5426,9 @@ opt_query_continuation
 //
 
 interactive_parsing
-       : INTERACTIVE_PARSER EOF 
-       | INTERACTIVE_PARSER_USING_DIRECTIVES using_directives { 
-               InteractiveResult = current_namespace; 
-         } 
-       | INTERACTIVE_PARSER { 
+       : EVAL_STATEMENT_PARSER EOF 
+       | EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives 
+       | EVAL_STATEMENT_PARSER { 
                InteractiveShell.LoadAliases (current_namespace);
 
                push_current_class (new Class (current_namespace, current_class, new MemberName ("Class" + class_count++),
@@ -5460,6 +5468,10 @@ interactive_parsing
                InteractiveResult = pop_current_class ();
                current_local_parameters = null;
          } 
+//     | EVAL_COMPILATION_UNIT_PARSER {
+//             InteractiveShell.LoadAliases (current_namespace);
+//       }
+//       compilation_unit
        ;
 %%
 
@@ -5553,10 +5565,17 @@ static void Error_TypeExpected (Location loc)
 
 void push_current_class (TypeContainer tc, object partial_token)
 {
+       if (RootContext.EvalMode){
+               tc.ModFlags = (tc.ModFlags & ~(Modifiers.PRIVATE|Modifiers.INTERNAL)) | Modifiers.PUBLIC;
+               undo.AddTypeContainer (current_container, tc);
+       }
+
        if (partial_token != null)
                current_container = current_container.AddPartial (tc);
        else
                current_container = current_container.AddTypeContainer (tc);
+
+
        current_class = tc;
 }
 
@@ -5599,7 +5618,7 @@ Block declare_local_variables (Expression type, ArrayList variable_declarators,
        // that are in the top block to be added instead to the class as 
        // static variables
        //
-       if (RootContext.EvalMode){
+       if (RootContext.StatementMode){
                bool hoist = true;
 
                for (Block b = current_block; b != null; b = b.Parent){
@@ -5627,7 +5646,7 @@ Block declare_local_variables (Expression type, ArrayList variable_declarators,
                                        assign = new SimpleAssign (new SimpleName (decl.identifier, decl.Location), var);
                                        current_block.AddStatement (new StatementExpression (assign));
                                } else {
-                                       Field f = new Field (current_container, (FullNamedExpression) type, Modifiers.NEW | Modifiers.PUBLIC | Modifiers.STATIC, decl.identifier, null, loc);
+                                       Field f = new Field (current_container, (FullNamedExpression) type, Modifiers.PUBLIC | Modifiers.STATIC, decl.identifier, null, loc);
                                        current_container.AddField (f);
 
                                        // Register the field to be visible later as a global variable
@@ -5758,6 +5777,9 @@ static CSharpParser ()
 
 public CSharpParser (SeekableStreamReader reader, CompilationUnit file)
 {
+       if (RootContext.EvalMode)
+               undo = new Undo ();
+
        this.file = file;
        current_namespace = new NamespaceEntry (null, file, null);
        current_class = current_namespace.SlaveDeclSpace;
@@ -5768,8 +5790,6 @@ public CSharpParser (SeekableStreamReader reader, CompilationUnit file)
 
 public void parse ()
 {
-       int errors = Report.Errors;
-
        eof_token = Token.EOF;
 
        try {
@@ -5780,13 +5800,16 @@ public void parse ()
        } catch (Exception e){
                if (e is yyParser.yyUnexpectedEof)
                        UnexpectedEOF = true;
-               if (Report.Errors == errors)
+               else if (yacc_verbose_flag > 0)
+                       Console.WriteLine (e);
+               if (e is yyParser.yyException)
                        Report.Error (-25, lexer.Location, "Parsing error");
+               else 
+                       Report.Error (-32, lexer.Location, "Internal compiler error during parsing, Run with -v for details");
        }
        Tokenizer tokenizer = lexer as Tokenizer;
        tokenizer.cleanup ();
 
-
        if (RootContext.ToplevelTypes.NamespaceEntry != null)
                throw new InternalErrorException ("who set it?");
 }
index 25782209577069c93a8540ea3f0ab716a0d8d58d..d53d5b4e402530b6a032fbd90d5e7c54ee2ee4db 100644 (file)
@@ -58,8 +58,9 @@ namespace Mono.CSharp
                // impact on the tokenizer's performance.
                //
                
-               public const int InteractiveParserCharacter = 0x2190;   // Unicode Left Arrow
-               public const int InteractiveParserCharacterUsing = 0x2191;   // Unicode Down Arrow
+               public const int EvalStatementParserCharacter = 0x2190;   // Unicode Left Arrow
+               public const int EvalCompilationUnitParserCharacter = 0x2191;  // Unicode Arrow
+               public const int EvalUsingDeclarationsParserCharacter = 0x2192;  // Unicode Arrow
                
                //
                // XML documentation buffer. The save point is used to divide
@@ -2785,11 +2786,12 @@ namespace Mono.CSharp
                                        }
                                }
 
-                               if (c == InteractiveParserCharacter)
-                                       return Token.INTERACTIVE_PARSER;
-                               
-                               if (c == InteractiveParserCharacterUsing)
-                                       return Token.INTERACTIVE_PARSER_USING_DIRECTIVES;
+                               if (c == EvalStatementParserCharacter)
+                                       return Token.EVAL_STATEMENT_PARSER;
+                               if (c == EvalCompilationUnitParserCharacter)
+                                       return Token.EVAL_COMPILATION_UNIT_PARSER;
+                               if (c == EvalUsingDeclarationsParserCharacter)
+                                       return Token.EVAL_USING_DECLARATIONS_UNIT_PARSER;
                                
                                error_details = ((char)c).ToString ();
                                
index 2858608c788a2479a431ae70d7e0e4985773ce82..8d5ac41b3acc011431e5ae24607a0739255557c4 100644 (file)
@@ -969,6 +969,11 @@ namespace Mono.CSharp {
                        return false;
                }
 
+               protected virtual void RemoveFromContainer (string name)
+               {
+                       defined_names.Remove (name);
+               }
+               
                /// <summary>
                ///   Returns the MemberCore associated with a given name in the declaration
                ///   space. It doesn't return method based symbols !!
index 30537869dbcdb34f2d95a31d6d3254834dc6694c..b6e6813e1f1ae6ca5e9d4ab7e0cd96678dfb45cb 100644 (file)
@@ -1985,17 +1985,22 @@ namespace Mono.CSharp
                        Reset (true);
                }
 
-               public static void Reset (bool full)
+               public static void PartialReset ()
+               {
+                       Reset (false);
+               }
+               
+               public static void Reset (bool full_flag)
                {
                        Driver.Reset ();
-                       RootContext.Reset ();
+                       RootContext.Reset (full_flag);
                        Tokenizer.Reset ();
                        Location.Reset ();
                        Report.Reset ();
                        TypeManager.Reset ();
                        TypeHandle.Reset ();
 
-                       if (full)
+                       if (full_flag)
                                RootNamespace.Reset ();
                        
                        NamespaceEntry.Reset ();
index 0879b4a36ccd0514bfe644e29b1c699d8e4f8424..d8856b9cbdd501f1883bebbb339bd3724a8a9909 100644 (file)
 // TODO:
 //    Enter an error (a = 1);  Notice how the prompt is in the wrong line
 //             This is caused by Stderr not being tracked by System.Console.
-//    Typing before the program start causes the cursor position to be wrong
-//              This is caused by Console not reading all the available data
-//              before sending the report-position sequence and reading it back.
 //    Completion support
-//    System.Console needs to get the DELETE character, and report accordingly.
 //    Why is Thread.Interrupt not working?   Currently I resort to Abort which is too much.
-//    Console needs SIGWINCH support of some sort
 //
+// Limitations in System.Console:
+//    Console needs SIGWINCH support of some sort
+//    Console needs a way of updating its position after things have been written
+//    behind its back (P/Invoke puts for example).
+//    System.Console needs to get the DELETE character, and report accordingly.
+//    Typing before the program start causes the cursor position to be wrong
+//              This is caused by Console not reading all the available data
+//              before sending the report-position sequence and reading it back.
 //
 #if NET_2_0 || NET_1_1
 #define IN_MCS_BUILD
@@ -33,6 +36,7 @@ using System;
 using System.Text;
 using System.IO;
 using System.Threading;
+using System.Reflection;
 
 namespace Mono.Terminal {
 
@@ -176,6 +180,8 @@ namespace Mono.Terminal {
                void CmdDebug ()
                {
                        history.Dump ();
+                       Console.WriteLine ();
+                       Render ();
                }
 
                void Render ()
@@ -729,7 +735,7 @@ namespace Mono.Terminal {
                        shown_prompt = prompt;
                        InitText (initial);
                        history.Append (initial);
-                       
+
                        do {
                                try {
                                        EditLoop ();
@@ -796,7 +802,8 @@ namespace Mono.Terminal {
                                                string line;
                                                
                                                while ((line = sr.ReadLine ()) != null){
-                                                       Append (line);
+                                                       if (line != "")
+                                                               Append (line);
                                                }
                                        }
                                }
index 7d2e31e0843325c333e343a0d97e7e96031ebe5c..b2eb712580db2582bb92c781e5cc9753eda3319a 100644 (file)
@@ -441,6 +441,15 @@ namespace Mono.CSharp {
                                        //
                                        tdecl.DefineType ();
                                        t = tdecl.TypeBuilder;
+
+                                       if (RootContext.EvalMode){
+                                               // Replace the TypeBuilder with a System.Type, as
+                                               // Reflection.Emit fails otherwise (we end up pretty
+                                               // much with Random type definitions later on).
+                                               Type tt = t.Assembly.GetType (t.Name);
+                                               if (tt != null)
+                                                       t = tt;
+                                       }
                                }
                        }
                        string lookup = t != null ? t.FullName : (fullname.Length == 0 ? name : fullname + "." + name);
@@ -544,6 +553,11 @@ namespace Mono.CSharp {
                        declspaces.Add (name, ds);
                }
 
+               public void RemoveDeclSpace (string name)
+               {
+                       declspaces.Remove (name);
+               }
+               
                /// <summary>
                ///   The qualified name of the current namespace
                /// </summary>
index 6dfa5a429dbe32809112936ae35cbd713abebcbf..934a064cfed505706d22b475e0efcc83bdc7c10e 100644 (file)
@@ -9,7 +9,11 @@
 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
 // Copyright 2004, 2005, 2006, 2007, 2008 Novell, Inc
 //
-// 
+//
+// TODO:
+//   Do not print results in Evaluate, do that elsewhere in preparation for Eval refactoring.
+//   Driver.PartialReset should not reset the coretypes, nor the optional types, to avoid
+//      computing that on every call.
 //
 using System;
 using System.IO;
@@ -68,12 +72,15 @@ namespace Mono.CSharp {
                                return editor.Edit (prompt, "");
                        }
                }
+
 #else
                static void SetupConsole ()
                {
                        // Here just to shut up the compiler warnings about unused invoking variable
                        if (invoking)
                                invoking = false;
+
+                       Console.Error.WriteLine ("Warning: limited functionality in 1.0 mode");
                }
 
                static string GetLine (bool primary)
@@ -85,13 +92,17 @@ namespace Mono.CSharp {
 
                        return Console.ReadLine ();
                }
+
 #endif
+               delegate string ReadLiner (bool primary);
 
                static void Reset ()
                {
-                       CompilerCallableEntryPoint.Reset (false);
-                       Driver.LoadReferences ();
+                       CompilerCallableEntryPoint.PartialReset ();
 
+                       //
+                       // PartialReset should not reset the core types, this is very redundant.
+                       //
                        if (!TypeManager.InitCoreTypes ())
                                throw new Exception ("Failed to InitCoreTypes");
                        TypeManager.InitOptionalCoreTypes ();
@@ -115,6 +126,11 @@ namespace Mono.CSharp {
                {
                        isatty = UnixUtils.isatty (0) && UnixUtils.isatty (1);
 
+                       // Work around, since Console is not accounting for
+                       // cursor position when writing to Stderr.  It also
+                       // has the undesirable side effect of making
+                       // errors plain, with no coloring.
+                       Report.Stderr = Console.Out;
                        SetupConsole ();
 
                        if (isatty)
@@ -122,18 +138,37 @@ namespace Mono.CSharp {
 
                }
 
-               static public int ReadEvalPrintLoop ()
+               static void LoadStartupFiles ()
                {
-                       InitTerminal ();
-                       RootContext.EvalMode = true;
+                       string dir = Path.Combine (
+                               Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData),
+                               "csharp");
+                       if (!Directory.Exists (dir))
+                               return;
 
-                       InitializeUsing ();
-                       
+                       foreach (string file in Directory.GetFiles (dir)){
+                               string l = file.ToLower ();
+                               
+                               if (l.EndsWith (".cs")){
+                                       try {
+                                               using (StreamReader r = File.OpenText (file)){
+                                                       ReadEvalPrintLoopWith (p => r.ReadLine ());
+                                               }
+                                       } catch {
+                                       }
+                               } else if (l.EndsWith (".dll")){
+                                       Driver.LoadAssembly (file, true);
+                               }
+                       }
+               }
+
+               static void ReadEvalPrintLoopWith (ReadLiner readline)
+               {
                        string expr = null;
                        while (true){
-                               string input = GetLine (expr == null);
+                               string input = readline (expr == null);
                                if (input == null)
-                                       return 0;
+                                       return;
 
                                if (input == "")
                                        continue;
@@ -143,6 +178,23 @@ namespace Mono.CSharp {
                                expr = Evaluate (expr);
                        } 
                }
+               
+               static public int ReadEvalPrintLoop ()
+               {
+                       CompilerCallableEntryPoint.Reset ();
+                       Driver.LoadReferences ();
+                       
+                       InitTerminal ();
+                       RootContext.EvalMode = true;
+
+                       InitializeUsing ();
+
+
+                       LoadStartupFiles ();
+                       ReadEvalPrintLoopWith (GetLine);
+
+                       return 0;
+               }
 
                
                static string Evaluate (string input)
@@ -156,10 +208,8 @@ namespace Mono.CSharp {
                                if (partial_input)
                                        return input;
                                
-                               if (parser == null){
-                                       ParseString (false, input, out partial_input);
-                                       return null;
-                               }
+                               ParseString (false, input, out partial_input);
+                               return null;
                        }
                        
                        // 
@@ -170,31 +220,136 @@ namespace Mono.CSharp {
                        //
                        object result = parser.InteractiveResult;
                        
-                       if (result is Class){
-                               try { 
-                                       object rval = ExecuteBlock ((Class) result);
-                                       
-                                       //
-                                       // We use a reference to a compiler type, in this case
-                                       // Driver as a flag to indicate that this was a statement
-                                       //
-                                       if (rval != typeof (NoValueSet)){
-                                               PrettyPrint (rval);
-                                               Console.WriteLine ();
-                                       }
-                               } catch (Exception e){
-                                       Console.WriteLine (e);
+                       try { 
+                               if (!(result is Class))
+                                       parser.CurrentNamespace.Extract (using_alias_list, using_list);
+
+                               object rval = ExecuteBlock (result as Class, parser.undo);
+                               //
+                               // We use a reference to a compiler type, in this case
+                               // Driver as a flag to indicate that this was a statement
+                               //
+                               if (rval != typeof (NoValueSet)){
+                                       PrettyPrint (rval);
+                                       Console.WriteLine ();
                                }
-                       } else if (result is NamespaceEntry){
-                               ((NamespaceEntry)result).Extract (using_alias_list, using_list);
-                       } else if (result == null){
-                               // Just a happy parse.
-                       } else {
-                               Console.Error.WriteLine ("Support for {0} is not available on the shell", parser.InteractiveResult);
+                       } catch (Exception e){
+                               Console.WriteLine (e);
                        }
                        return null;
                }
 
+               enum InputKind {
+                       EOF,
+                       StatementOrExpression,
+                       CompilationUnit,
+                       Error
+               }
+
+               //
+               // Deambiguates the input string to determine if we
+               // want to process a statement or if we want to
+               // process a compilation unit.
+               //
+               // This is done using a top-down predictive parser,
+               // since the yacc/jay parser can not deambiguage this
+               // without more than one lookahead token.   There are very
+               // few ambiguities.
+               //
+               static InputKind ToplevelOrStatement (SeekableStreamReader seekable)
+               {
+                       Tokenizer tokenizer = new Tokenizer (seekable, Location.SourceFiles [0]);
+                       
+                       int t = tokenizer.token ();
+                       switch (t){
+                       case Token.EOF:
+                               return InputKind.EOF;
+                               
+                       // These are toplevels
+                       case Token.EXTERN:
+                       case Token.OPEN_BRACKET:
+                       case Token.ABSTRACT:
+                       case Token.CLASS:
+                       case Token.ENUM:
+                       case Token.INTERFACE:
+                       case Token.INTERNAL:
+                       case Token.NAMESPACE:
+                       case Token.PRIVATE:
+                       case Token.PROTECTED:
+                       case Token.PUBLIC:
+                       case Token.SEALED:
+                       case Token.STATIC:
+                       case Token.STRUCT:
+                               return InputKind.CompilationUnit;
+                               
+                       // Definitely expression
+                       case Token.FIXED:
+                       case Token.BOOL:
+                       case Token.BYTE:
+                       case Token.CHAR:
+                       case Token.DECIMAL:
+                       case Token.DOUBLE:
+                       case Token.FLOAT:
+                       case Token.INT:
+                       case Token.LONG:
+                       case Token.NEW:
+                       case Token.OBJECT:
+                       case Token.SBYTE:
+                       case Token.SHORT:
+                       case Token.STRING:
+                       case Token.UINT:
+                       case Token.ULONG:
+                               return InputKind.StatementOrExpression;
+
+                       // These need deambiguation help
+                       case Token.USING:
+                               t = tokenizer.token ();
+                               if (t == Token.EOF)
+                                       return InputKind.EOF;
+
+                               if (t == Token.IDENTIFIER)
+                                       return InputKind.CompilationUnit;
+                               return InputKind.StatementOrExpression;
+
+
+                       // Distinguish between:
+                       //    delegate opt_anonymous_method_signature block
+                       //    delegate type 
+                       case Token.DELEGATE:
+                               t = tokenizer.token ();
+                               if (t == Token.EOF)
+                                       return InputKind.EOF;
+                               if (t == Token.OPEN_PARENS || t == Token.OPEN_BRACE)
+                                       return InputKind.StatementOrExpression;
+                               return InputKind.CompilationUnit;
+
+                       // Distinguih between:
+                       //    unsafe block
+                       //    unsafe as modifier of a type declaration
+                       case Token.UNSAFE:
+                               t = tokenizer.token ();
+                               if (t == Token.EOF)
+                                       return InputKind.EOF;
+                               if (t == Token.OPEN_PARENS)
+                                       return InputKind.StatementOrExpression;
+                               return InputKind.CompilationUnit;
+                               
+                       // These are errors: we list explicitly what we had
+                       // from the grammar, ERROR and then everything else
+
+                       case Token.READONLY:
+                       case Token.OVERRIDE:
+                       case Token.ERROR:
+                               return InputKind.Error;
+
+                       // This catches everything else allowed by
+                       // expressions.  We could add one-by-one use cases
+                       // if needed.
+                       default:
+                               return InputKind.StatementOrExpression;
+                       }
+               }
+               
                //
                // Parses the string @input and returns a CSharpParser if succeeful.
                //
@@ -210,25 +365,44 @@ namespace Mono.CSharp {
                        partial_input = false;
                        Reset ();
                        queued_fields.Clear ();
-                       
+
                        Stream s = new MemoryStream (Encoding.Default.GetBytes (input));
                        SeekableStreamReader seekable = new SeekableStreamReader (s, Encoding.Default);
-                       Tokenizer t = new Tokenizer (seekable, Location.SourceFiles [0]);
 
-                       //
-                       // Deambiguate: do we have a using statement, or a using clause
-                       //
-                       int initial_token;
-                       if (t.token () == Token.USING && t.token () == Token.IDENTIFIER)
-                               initial_token = Tokenizer.InteractiveParserCharacterUsing;
-                       else
-                               initial_token = Tokenizer.InteractiveParserCharacter;
+                       InputKind kind = ToplevelOrStatement (seekable);
+                       if (kind == InputKind.Error){
+                               if (!silent)
+                                       Report.Error (-25, "Detection Parsing Error");
+                               partial_input = false;
+                               return null;
+                       }
+
+                       if (kind == InputKind.EOF){
+                               if (silent == false)
+                                       Console.Error.WriteLine ("Internal error: EOF condition should have been detected in a previous call with silent=true");
+                               partial_input = true;
+                               return null;
+                               
+                       }
                        seekable.Position = 0;
 
                        CSharpParser parser = new CSharpParser (seekable, Location.SourceFiles [0]);
                        parser.ErrorOutput = Report.Stderr;
 
-                       parser.Lexer.putback_char = initial_token;
+                       if (kind == InputKind.StatementOrExpression){
+                               parser.Lexer.putback_char = Tokenizer.EvalStatementParserCharacter;
+                               RootContext.StatementMode = true;
+                       } else {
+                               //
+                               // Do not activate EvalCompilationUnitParserCharacter until
+                               // I have figured out all the limitations to invoke methods
+                               // in the generated classes.  See repl.txt
+                               //
+                               parser.Lexer.putback_char = Tokenizer.EvalUsingDeclarationsParserCharacter;
+                               //parser.Lexer.putback_char = Tokenizer.EvalCompilationUnitParserCharacter;
+                               RootContext.StatementMode = false;
+                       }
+
                        if (silent)
                                Report.DisableReporting ();
                        try {
@@ -237,13 +411,14 @@ namespace Mono.CSharp {
                                if (Report.Errors != 0){
                                        if (silent && parser.UnexpectedEOF)
                                                partial_input = true;
+
+                                       parser.undo.ExecuteUndo ();
                                        parser = null;
                                }
 
                                if (silent)
                                        Report.EnableReporting ();
                        }
-
                        return parser;
                }
 
@@ -296,33 +471,44 @@ namespace Mono.CSharp {
                //
                static ArrayList queued_fields = new ArrayList ();
                
-               static ArrayList types = new ArrayList ();
+               //static ArrayList types = new ArrayList ();
 
                static volatile bool invoking;
                
-               static object ExecuteBlock (Class host)
+               static object ExecuteBlock (Class host, Undo undo)
                {
                        RootContext.ResolveTree ();
+                       if (Report.Errors != 0){
+                               undo.ExecuteUndo ();
+                               return typeof (NoValueSet);
+                       }
+                       
                        RootContext.PopulateTypes ();
                        RootContext.DefineTypes ();
 
-                       if (Report.Errors != 0)
+                       if (Report.Errors != 0){
+                               undo.ExecuteUndo ();
                                return typeof (NoValueSet);
+                       }
 
-                       TypeBuilder tb = host.TypeBuilder;
-                       types.Add (tb);
+                       TypeBuilder tb = null;
                        MethodBuilder mb = null;
-                       foreach (MemberCore member in host.Methods){
-                               if (member.Name != "Host")
-                                       continue;
+                               
+                       if (host != null){
+                               tb = host.TypeBuilder;
+                               mb = null;
+                               foreach (MemberCore member in host.Methods){
+                                       if (member.Name != "Host")
+                                               continue;
+                                       
+                                       MethodOrOperator method = (MethodOrOperator) member;
+                                       mb = method.MethodBuilder;
+                                       break;
+                               }
 
-                               MethodOrOperator method = (MethodOrOperator) member;
-                               mb = method.MethodBuilder;
-                               break;
+                               if (mb == null)
+                                       throw new Exception ("Internal error: did not find the method builder for the generated method");
                        }
-
-                       if (mb == null)
-                               throw new Exception ("Internal error: did not find the method builder for the generated method");
                        
                        RootContext.EmitCode ();
                        if (Report.Errors != 0)
@@ -333,19 +519,22 @@ namespace Mono.CSharp {
                        if (Environment.GetEnvironmentVariable ("SAVE") != null)
                                CodeGen.Save (current_debug_name, false);
 
+                       if (host == null)
+                               return typeof (NoValueSet);
+                       
                        //
                        // Unlike Mono, .NET requires that the MethodInfo is fetched, it cant
                        // work from MethodBuilders.   Retarded, I know.
                        //
                        Type tt = CodeGen.Assembly.Builder.GetType (tb.Name);
                        MethodInfo mi = tt.GetMethod (mb.Name);
-
+                       
                        // Pull the FieldInfos from the type, and keep track of them
                        foreach (Field field in queued_fields){
                                FieldInfo fi = tt.GetField (field.Name);
-
+                               
                                FieldInfo old = (FieldInfo) fields [field.Name];
-
+                               
                                // If a previous value was set, nullify it, so that we do
                                // not leak memory
                                if (old != null){
@@ -359,11 +548,13 @@ namespace Mono.CSharp {
                                
                                fields [field.Name] = fi;
                        }
+                       //types.Add (tb);
+
                        queued_fields.Clear ();
                        
                        HostSignature invoker = (HostSignature) System.Delegate.CreateDelegate (typeof (HostSignature), mi);
                        object retval = typeof (NoValueSet);
-
+                       
                        try {
                                invoking = true;
                                invoker (ref retval);
@@ -373,7 +564,7 @@ namespace Mono.CSharp {
                        } finally {
                                invoking = false;
                        }
-
+                       
                        // d.DynamicInvoke  (new object [] { retval });
 
                        return retval;
@@ -466,7 +657,7 @@ namespace Mono.CSharp {
                                return null;
 
                        Field f = new Field (container, new TypeExpression (ret.Type, Location),
-                                            Modifiers.NEW | Modifiers.PUBLIC | Modifiers.STATIC,
+                                            Modifiers.PUBLIC | Modifiers.STATIC,
                                             name, null, Location);
                        container.AddField (f);
                        if (f.Define ())
@@ -526,6 +717,40 @@ namespace Mono.CSharp {
                }
        }
 
+       public class Undo {
+               ArrayList undo_types;
+               
+               public Undo ()
+               {
+                       undo_types = new ArrayList ();
+               }
+
+               public void AddTypeContainer (TypeContainer current_container, TypeContainer tc)
+               {
+                       if (current_container == tc){
+                               Console.Error.WriteLine ("Internal error: inserting container into itself");
+                               return;
+                       }
+                       
+                       if (undo_types == null)
+                               undo_types = new ArrayList ();
+                       undo_types.Add (new Pair (current_container, tc));
+               }
+
+               public void ExecuteUndo ()
+               {
+                       if (undo_types == null)
+                               return;
+
+                       foreach (Pair p in undo_types){
+                               TypeContainer current_container = (TypeContainer) p.First;
+
+                               current_container.RemoveTypeContainer ((TypeContainer) p.Second);
+                       }
+                       undo_types = null;
+               }
+       }
+       
        /// <summary>
        ///   The base class for every interaction line
        /// </summary>
index 36a055259c902c6484cba3649235e1b4572cb514..814a9946f13ba9de321123941926cec112ccd690 100644 (file)
@@ -12,21 +12,69 @@ Mono, or go to mcs and type:
 
 * Mix statements with other top-level declarations.
 
-       Currently we only process statements, but it would be useful
-       to define classes, interfaces and structs inline.   
+csharp> class Y {static void Main () {Console.WriteLine ("Foo"); }}
+csharp> typeof (Y);
+Y
+csharp> Y.Main ();
+Exception caught by the compiler while compiling:
+   Block that caused the problem begin at: Internal(1,1):
+                     Block being compiled: [<interactive>(1,2):,<interactive>(1,11):]
+System.NotSupportedException: The invoked member is not supported in a dynamic module.
+Internal compiler error at Internal(1,1):: exception caught while emitting MethodBuilder [Class2::Host]
+System.NotSupportedException: The invoked member is not supported in a dynamic module.
+  at System.Reflection.Emit.AssemblyBuilder.get_Location () [0x00000] in /second/home/cvs/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs:214 
+  at Mono.CSharp.Report.SymbolRelatedToPreviousError (System.Reflection.MemberInfo mi) [0x00036] in /second/home/cvs/mcs/mcs/report.cs:664 
+  at Mono.CSharp.Expression.Error_MemberLookupFailed (System.Type container_type, System.Type qualifier_type, System.Type queried_type, System.String name, System.String class_name, MemberTypes mt, BindingFlags bf) [0x00121] in /second/home/cvs/mcs/mcs/ecore.cs:857 
+  at Mono.CSharp.MemberAccess.DoResolve (Mono.CSharp.EmitContext ec, Mono.CSharp.Expression right_side) [0x00230] in /second/home/cvs/mcs/mcs/expression.cs:7426 
+  at Mono.CSharp.MemberAccess.DoResolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/expression.cs:7494 
+  at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 
+  at Mono.CSharp.Invocation.DoResolve (Mono.CSharp.EmitContext ec) [0x0000d] in /second/home/cvs/mcs/mcs/expression.cs:4725 
+  at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 
+  at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 
+  at Mono.CSharp.OptionalAssign.DoResolve (Mono.CSharp.EmitContext ec) [0x00013] in /second/home/cvs/mcs/mcs/repl.cs:681 
+  at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 
+  at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 
+  at Mono.CSharp.ExpressionStatement.ResolveStatement (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:1307 
+  at Mono.CSharp.StatementExpression.Resolve (Mono.CSharp.EmitContext ec) [0x0000b] in /second/home/cvs/mcs/mcs/statement.cs:743 
+  at Mono.CSharp.Block.Resolve (Mono.CSharp.EmitContext ec) [0x000f0] in /second/home/cvs/mcs/mcs/statement.cs:2254 
+  at Mono.CSharp.ExplicitBlock.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/statement.cs:2550 
+  at Mono.CSharp.EmitContext.ResolveTopBlock (Mono.CSharp.EmitContext anonymous_method_host, Mono.CSharp.ToplevelBlock block, Mono.CSharp.Parameters ip, IMethodData md, System.Boolean& unreachable) [0x00087] in /second/home/cvs/mcs/mcs/codegen.cs:796 
+csharp>  
+
+* Another one:
+
+csharp> class X { X (){ Console.WriteLine ("Called"); } }              
+csharp> new X ();
+Exception caught by the compiler while compiling:
+   Block that caused the problem begin at: Internal(1,1):
+                     Block being compiled: [<interactive>(1,2):,<interactive>(1,10):]
+System.NotSupportedException: The invoked member is not supported in a dynamic module.
+Internal compiler error at Internal(1,1):: exception caught while emitting MethodBuilder [Class0::Host]
+System.NotSupportedException: The invoked member is not supported in a dynamic module.
+  at System.Reflection.Emit.AssemblyBuilder.get_Location () [0x00000] in /second/home/cvs/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs:214 
+  at Mono.CSharp.Report.SymbolRelatedToPreviousError (System.Reflection.MemberInfo mi) [0x00036] in /second/home/cvs/mcs/mcs/report.cs:664 
+  at Mono.CSharp.Expression.Error_MemberLookupFailed (System.Type container_type, System.Type qualifier_type, System.Type queried_type, System.String name, System.String class_name, MemberTypes mt, BindingFlags bf) [0x00121] in /second/home/cvs/mcs/mcs/ecore.cs:857 
+  at Mono.CSharp.Expression.MemberLookupFinal (Mono.CSharp.EmitContext ec, System.Type qualifier_type, System.Type queried_type, System.String name, MemberTypes mt, BindingFlags bf, Location loc) [0x0002f] in /second/home/cvs/mcs/mcs/ecore.cs:804 
+  at Mono.CSharp.New.DoResolve (Mono.CSharp.EmitContext ec) [0x002ad] in /second/home/cvs/mcs/mcs/expression.cs:5486 
+  at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 
+  at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 
+  at Mono.CSharp.OptionalAssign.DoResolve (Mono.CSharp.EmitContext ec) [0x00013] in /second/home/cvs/mcs/mcs/repl.cs:687 
+  at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 
+  at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 
+  at Mono.CSharp.ExpressionStatement.ResolveStatement (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:1307 
+  at Mono.CSharp.StatementExpression.Resolve (Mono.CSharp.EmitContext ec) [0x0000b] in /second/home/cvs/mcs/mcs/statement.cs:743 
+  at Mono.CSharp.Block.Resolve (Mono.CSharp.EmitContext ec) [0x000f0] in /second/home/cvs/mcs/mcs/statement.cs:2254 
+  at Mono.CSharp.ExplicitBlock.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/statement.cs:2550 
+  at Mono.CSharp.EmitContext.ResolveTopBlock (Mono.CSharp.EmitContext anonymous_method_host, Mono.CSharp.ToplevelBlock block, Mono.CSharp.Parameters ip, IMethodData md, System.Boolean& unreachable) [0x00087] in /second/home/cvs/mcs/mcs/codegen.cs:796 
+csharp>  
+
+* Important: we need to replace TypeBuidlers with Types after things
+  have been emitted, or stuff like this happens:
+
+csharp> public class y  {}
+csharp> typeof (y); 
+Class1
 
-       These pose a problem, as the grammar conflicts on a few 
-       elements like delegate (delegate declaration or anonymous
-       method declration).
-
-       To address this issue, I should build a mini-parser into
-       repl.cs that does an initial pass at the input stream and
-       determines with as many lookahead tokens as needed whether the
-       text is regular toplevel declaration or our statement
-       declaration.
-
-       This would solve the grammar ambiguity that happens if we just
-       allow both to be starting nodes.
 
 * Clearing data
 
index de3aae884bdcbdadaa1aba5144691e85711ffa47..22c784d62b7ab3baa085304bc20a1439d7a1e03b 100644 (file)
@@ -66,10 +66,18 @@ namespace Mono.CSharp {
 
                //
                // If true, it means that the compiler is executing as
-               // in eval mode.
+               // in eval mode so unresolved variables are resolved in
+               // static classes maintained by the eval engine.
                //
                static public bool EvalMode;
 
+               //
+               // If true, the compiler is operating in statement mode,
+               // this currently turns local variable declaration into
+               // static variables of a class
+               //
+               static public bool StatementMode;
+               
                //
                // Whether to allow Unsafe code
                //
@@ -125,12 +133,19 @@ namespace Mono.CSharp {
                //
                static RootContext ()
                {
-                       Reset ();
+                       Reset (true);
                }
 
-               public static void Reset ()
+               public static void PartialReset ()
                {
-                       root = new RootTypes ();
+                       Reset (false);
+               }
+               
+               public static void Reset (bool full)
+               {
+                       if (full)
+                               root = new RootTypes ();
+                       
                        type_container_resolve_order = new ArrayList ();
                        EntryPoint = null;
                        Report.WarningLevel = 4;
index d2492778b419e13e8d28776ff1fb17aa030dd876..a26900c0756eb94a7729e90569d805733e35b3e7 100644 (file)
@@ -25,7 +25,7 @@ namespace Mono.CSharp
        {
                // TODO: It'd be so nice to have generics
                Hashtable anonymous_types;
-
+               
                public RootTypes ()
                        : base (null, null, MemberName.Null, null, Kind.Root)
                {
@@ -86,10 +86,17 @@ namespace Mono.CSharp
                        return true;
                }
 
+               protected override void RemoveMemberType (DeclSpace ds)
+               {
+                       ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
+                       base.RemoveMemberType (ds);
+               }
+               
                public override TypeContainer AddPartial (TypeContainer nextPart)
                {
                        return AddPartial (nextPart, nextPart.Name);
                }
+
        }
 
        public class RootDeclSpace : DeclSpace {