// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2004, 2005, 2006, 2007, 2008 Novell, Inc
//
+
using System;
using System.Threading;
using System.Collections.Generic;
using System.Reflection.Emit;
using System.IO;
using System.Text;
+using System.Linq;
-namespace Mono.CSharp {
+namespace Mono.CSharp
+{
/// <summary>
/// Evaluator: provides an API to evaluate C# statements and
static int count;
static Thread invoke_thread;
- static List<NamespaceEntry.UsingAliasEntry> using_alias_list = new List<NamespaceEntry.UsingAliasEntry> ();
- internal static List<NamespaceEntry.UsingEntry> using_list = new List<NamespaceEntry.UsingEntry> ();
static Dictionary<string, Tuple<FieldSpec, FieldInfo>> fields = new Dictionary<string, Tuple<FieldSpec, FieldInfo>> ();
static TypeSpec interactive_base_class;
static CompilerContext ctx;
static DynamicLoader loader;
+ static NamespaceEntry ns;
public static TextWriter MessageOutput = Console.Out;
return ctx.Report.SetPrinter (report_printer);
}
+ public static string [] InitAndGetStartupFiles (string [] args)
+ {
+ return InitAndGetStartupFiles (args, null);
+ }
+
/// <summary>
/// Optional initialization for the Evaluator.
/// </summary>
///
/// This method return an array of strings that contains any
/// files that were specified in `args'.
+ ///
+ /// If the unknownOptionParser is not null, this function is invoked
+ /// with the current args array and the index of the option that is not
+ /// known. A value of true means that the value was processed, otherwise
+ /// it will be reported as an error
/// </remarks>
- public static string [] InitAndGetStartupFiles (string [] args)
+ public static string [] InitAndGetStartupFiles (string [] args, Func<string [], int, int> unknownOptionParser)
{
lock (evaluator_lock){
if (inited)
return new string [0];
-
- driver = Driver.Create (args, false, new ConsoleReportPrinter ());
- if (driver == null)
+
+ CompilerCallableEntryPoint.Reset ();
+ var r = new Report (new ConsoleReportPrinter ());
+ var cmd = new CommandLineParser (r);
+ if (unknownOptionParser != null)
+ cmd.UnknownOptionHandler += unknownOptionParser;
+
+ var settings = cmd.ParseArguments (args);
+
+ // TODO: Should use ReportPrinter with throw instead of this
+ if (settings == null || r.Errors > 0)
throw new Exception ("Failed to create compiler driver with the given arguments");
- ctx = driver.ctx;
+ ctx = new CompilerContext (settings, r) {
+ IsEvalutor = true
+ };
RootContext.ToplevelTypes = new ModuleContainer (ctx);
foreach (CompilationUnit file in Location.SourceFiles)
startup_files.Add (file.Path);
- CompilerCallableEntryPoint.Reset ();
+ CompilerCallableEntryPoint.PartialReset ();
var importer = new ReflectionImporter (ctx.BuildinTypes);
loader = new DynamicLoader (importer, ctx);
- RootContext.ToplevelTypes.MakeExecutable ("temp");
+ RootContext.ToplevelTypes.SetDeclaringAssembly (new AssemblyDefinitionDynamic (RootContext.ToplevelTypes, "temp"));
+
loader.LoadReferences (RootContext.ToplevelTypes);
- TypeManager.InitCoreTypes (RootContext.ToplevelTypes, ctx.BuildinTypes);
+ ctx.BuildinTypes.CheckDefinitions (RootContext.ToplevelTypes);
RootContext.ToplevelTypes.InitializePredefinedTypes ();
- RootContext.EvalMode = true;
inited = true;
return startup_files.ToArray ();
if (type == null)
throw new ArgumentNullException ();
+ if (!inited)
+ throw new Exception ("Evaluator has to be initiated before seting custom InteractiveBase class");
+
lock (evaluator_lock)
interactive_base_class = loader.Importer.ImportType (type);
}
compiled = null;
return null;
}
-
+
lock (evaluator_lock){
if (!inited)
Init ();
+ else
+ ctx.Report.Printer.Reset ();
// RootContext.ToplevelTypes = new ModuleContainer (ctx);
return null;
}
- object parser_result = parser.InteractiveResult;
-
- if (!(parser_result is Class)){
- int errors = ctx.Report.Errors;
-
- NamespaceEntry.VerifyAllUsing ();
- if (errors == ctx.Report.Errors)
- parser.CurrentNamespace.Extract (using_alias_list, using_list);
- }
-
- compiled = CompileBlock (parser_result as Class, parser.undo, ctx.Report);
+#if STATIC
+ throw new NotSupportedException ();
+#else
+ Class parser_result = parser.InteractiveResult;
+ compiled = CompileBlock (parser_result, parser.undo, ctx.Report);
+ return null;
+#endif
}
-
- return null;
}
/// <summary>
return null;
}
- Class parser_result = parser.InteractiveResult as Class;
-
- if (parser_result == null){
- if (CSharpParser.yacc_verbose_flag != 0)
- Console.WriteLine ("Do not know how to cope with !Class yet");
- return null;
- }
+ Class parser_result = parser.InteractiveResult;
try {
- var a = RootContext.ToplevelTypes.MakeExecutable ("temp");
+ var a = new AssemblyDefinitionDynamic (RootContext.ToplevelTypes, "temp");
a.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.Run);
+ RootContext.ToplevelTypes.SetDeclaringAssembly (a);
+ RootContext.ToplevelTypes.CreateType ();
RootContext.ToplevelTypes.Define ();
+
+ parser_result.CreateType ();
+ parser_result.Define ();
if (ctx.Report.Errors != 0)
return null;
return cr.Result;
}
} finally {
- parser.undo.ExecuteUndo ();
+ if (parser.undo != null)
+ parser.undo.ExecuteUndo ();
}
}
return null;
}
-
+
/// <summary>
/// Executes the given expression or statement.
/// </summary>
return result;
}
-
+
enum InputKind {
EOF,
StatementOrExpression,
}
seekable.Position = 0;
- CSharpParser parser = new CSharpParser (seekable, Location.SourceFiles [0], RootContext.ToplevelTypes);
+ if (ns == null)
+ ns = new NamespaceEntry (RootContext.ToplevelTypes, null, Location.SourceFiles[0], null);
+
+ CSharpParser parser = new CSharpParser (seekable, Location.SourceFiles [0], RootContext.ToplevelTypes, ns);
if (kind == InputKind.StatementOrExpression){
parser.Lexer.putback_char = Tokenizer.EvalStatementParserCharacter;
- RootContext.StatementMode = true;
+ ctx.Settings.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;
+ parser.Lexer.putback_char = Tokenizer.EvalCompilationUnitParserCharacter;
+ ctx.Settings.StatementMode = false;
}
if (mode == ParseMode.GetCompletions)
if (mode != ParseMode.ReportErrors && parser.UnexpectedEOF)
partial_input = true;
- parser.undo.ExecuteUndo ();
+ if (parser.undo != null)
+ parser.undo.ExecuteUndo ();
+
parser = null;
}
//static ArrayList types = new ArrayList ();
static volatile bool invoking;
-
+#if !STATIC
static CompiledMethod CompileBlock (Class host, Undo undo, Report Report)
{
- AssemblyDefinition assembly;
+ AssemblyDefinitionDynamic assembly;
+ AssemblyBuilderAccess access;
if (Environment.GetEnvironmentVariable ("SAVE") != null) {
- assembly = RootContext.ToplevelTypes.MakeExecutable (current_debug_name, current_debug_name);
+ access = AssemblyBuilderAccess.RunAndSave;
+ assembly = new AssemblyDefinitionDynamic (RootContext.ToplevelTypes, current_debug_name, current_debug_name);
assembly.Importer = loader.Importer;
} else {
- assembly = RootContext.ToplevelTypes.MakeExecutable (current_debug_name);
+#if NET_4_0
+ access = AssemblyBuilderAccess.RunAndCollect;
+#else
+ access = AssemblyBuilderAccess.Run;
+#endif
+ assembly = new AssemblyDefinitionDynamic (RootContext.ToplevelTypes, current_debug_name);
}
- assembly.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.RunAndSave);
+ assembly.Create (AppDomain.CurrentDomain, access);
+
+ if (host != null) {
+ host.CreateType ();
+ host.Define ();
+ }
+
+ RootContext.ToplevelTypes.CreateType ();
RootContext.ToplevelTypes.Define ();
if (Report.Errors != 0){
- undo.ExecuteUndo ();
+ if (undo != null)
+ undo.ExecuteUndo ();
+
return null;
}
if (mb == null)
throw new Exception ("Internal error: did not find the method builder for the generated method");
+
+ host.EmitType ();
}
RootContext.ToplevelTypes.Emit ();
if (Report.Errors != 0){
- undo.ExecuteUndo ();
+ if (undo != null)
+ undo.ExecuteUndo ();
return null;
}
RootContext.ToplevelTypes.CloseType ();
+ if (host != null)
+ host.CloseType ();
- if (Environment.GetEnvironmentVariable ("SAVE") != null)
+ if (access == AssemblyBuilderAccess.RunAndSave)
assembly.Save ();
if (host == null)
}
}
- fields [field.Name] = Tuple.Create (old.Item1, fi);
+ fields [field.Name] = Tuple.Create (field.Spec, fi);
} else {
fields.Add (field.Name, Tuple.Create (field.Spec, fi));
}
}
- //types.Add (tb);
-
queued_fields.Clear ();
return (CompiledMethod) System.Delegate.CreateDelegate (typeof (CompiledMethod), mi);
}
-
- static internal void LoadAliases (NamespaceEntry ns)
- {
- ns.Populate (using_alias_list, using_list);
- }
-
+#endif
+
/// <summary>
/// A sentinel value used to indicate that no value was
/// was set by the compiled function. This is used to
static public string GetUsing ()
{
lock (evaluator_lock){
+ if (ns == null)
+ return null;
+
StringBuilder sb = new StringBuilder ();
-
- foreach (object x in using_alias_list)
- sb.Append (String.Format ("using {0};\n", x));
-
- foreach (object x in using_list)
- sb.Append (String.Format ("using {0};\n", x));
+ // TODO:
+ //foreach (object x in ns.using_alias_list)
+ // sb.AppendFormat ("using {0};\n", x);
+
+ foreach (var ue in ns.Usings) {
+ sb.AppendFormat ("using {0};", ue.ToString ());
+ sb.Append (Environment.NewLine);
+ }
return sb.ToString ();
}
static internal ICollection<string> GetUsingList ()
{
- var res = new List<string> (using_list.Count);
- foreach (object ue in using_list)
+ var res = new List<string> ();
+
+ foreach (var ue in ns.Usings)
res.Add (ue.ToString ());
return res;
}
static public void LoadAssembly (string file)
{
lock (evaluator_lock){
- var a = loader.LoadAssemblyFile (file, false);
+ var a = loader.LoadAssemblyFile (file);
if (a != null)
loader.Importer.ImportAssembly (a, RootContext.ToplevelTypes.GlobalRootNamespace);
}
return DateTime.Now - start;
}
-#if !SMCS_SOURCE
+#if !STATIC
/// <summary>
/// Loads the assemblies from a package
/// </summary>
}
#endif
+#if !STATIC
/// <summary>
/// Loads the assembly
/// </summary>
{
Evaluator.LoadAssembly (assembly);
}
+
+ static public void print (string obj)
+ {
+ Output.WriteLine (obj);
+ }
+
+ static public void print (string fmt, params object [] args)
+ {
+ Output.WriteLine (fmt, args);
+ }
+#endif
/// <summary>
/// Returns a list of available static methods.
" Prompt - The prompt used by the C# shell\n" +
" ContinuationPrompt - The prompt for partial input\n" +
" Time(() -> { }) - Times the specified code\n" +
+ " print (obj) - Shorthand for Console.WriteLine\n" +
" quit; - You'll never believe it - this quits the repl!\n" +
" help; - This help text\n";
}
}
}
- public class Undo {
- List<KeyValuePair<TypeContainer, TypeContainer>> undo_types;
+ public class Undo
+ {
+ List<Action> undo_actions;
public Undo ()
{
- undo_types = new List<KeyValuePair<TypeContainer, TypeContainer>> ();
}
public void AddTypeContainer (TypeContainer current_container, TypeContainer tc)
return;
}
- if (undo_types == null)
- undo_types = new List<KeyValuePair<TypeContainer, TypeContainer>> ();
+ if (undo_actions == null)
+ undo_actions = new List<Action> ();
+
+ var existing = current_container.Types.FirstOrDefault (l => l.MemberName.Basename == tc.MemberName.Basename);
+ if (existing != null) {
+ current_container.RemoveTypeContainer (existing);
+ undo_actions.Add (() => current_container.AddTypeContainer (existing));
+ }
- undo_types.Add (new KeyValuePair<TypeContainer, TypeContainer> (current_container, tc));
+ undo_actions.Add (() => current_container.RemoveTypeContainer (tc));
}
public void ExecuteUndo ()
{
- if (undo_types == null)
+ if (undo_actions == null)
return;
- foreach (var p in undo_types){
- TypeContainer current_container = p.Key;
-
- current_container.RemoveTypeContainer (p.Value);
+ foreach (var p in undo_actions){
+ p ();
}
- undo_types = null;
+
+ undo_actions = null;
}
}
}
-