//
// Authors:
// Miguel de Icaza (miguel@gnome.org)
+// Marek Safar (marek.safar@gmail.com)
//
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
-// Copyright 2004, 2005, 2006, 2007, 2008 Novell, Inc
+// Copyright 2004-2011 Novell, Inc
//
using System;
}
static object evaluator_lock = new object ();
+ static volatile bool invoking;
- static string current_debug_name;
static int count;
static Thread invoke_thread;
- static Dictionary<string, Tuple<FieldSpec, FieldInfo>> fields = new Dictionary<string, Tuple<FieldSpec, FieldInfo>> ();
+ readonly Dictionary<string, Tuple<FieldSpec, FieldInfo>> fields;
- static TypeSpec interactive_base_class;
- static bool inited;
+ Type base_class;
+ bool inited;
- static CompilerContext ctx;
- static DynamicLoader loader;
- static NamespaceEntry ns;
- static ModuleContainer module;
-
- public static TextWriter MessageOutput = Console.Out;
+ readonly CompilerContext ctx;
+ readonly ModuleContainer module;
+ readonly ReflectionImporter importer;
- /// <summary>
- /// Optional initialization for the Evaluator.
- /// </summary>
- /// <remarks>
- /// Initializes the Evaluator with the command line options
- /// that would be processed by the command line compiler. Only
- /// the first call to Init will work, any future invocations are
- /// ignored.
- ///
- /// You can safely avoid calling this method if your application
- /// does not need any of the features exposed by the command line
- /// interface.
- /// </remarks>
- public static void Init (string [] args)
+ // TODO: somehow merge with module
+ NamespaceEntry ns;
+
+ public Evaluator (CompilerSettings settings, Report report)
{
- InitAndGetStartupFiles (args);
- }
+ ctx = new CompilerContext (settings, report);
- internal static ReportPrinter SetPrinter (ReportPrinter report_printer)
- {
- return ctx.Report.SetPrinter (report_printer);
- }
+ module = new ModuleContainer (ctx);
+ module.Evaluator = this;
- public static string [] InitAndGetStartupFiles (string [] args)
- {
- return InitAndGetStartupFiles (args, null);
+ // FIXME: Importer needs this assembly for internalsvisibleto
+ module.SetDeclaringAssembly (new AssemblyDefinitionDynamic (module, "evaluator"));
+ importer = new ReflectionImporter (module, ctx.BuildinTypes);
+
+ InteractiveBaseClass = typeof (InteractiveBase);
+ fields = new Dictionary<string, Tuple<FieldSpec, FieldInfo>> ();
}
- /// <summary>
- /// Optional initialization for the Evaluator.
- /// </summary>
- /// <remarks>
- /// Initializes the Evaluator with the command line
- /// options that would be processed by the command
- /// line compiler. Only the first call to
- /// InitAndGetStartupFiles or Init will work, any future
- /// invocations are ignored.
- ///
- /// You can safely avoid calling this method if your application
- /// does not need any of the features exposed by the command line
- /// interface.
- ///
- /// 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, Func<string [], int, int> unknownOptionParser)
+ void Init ()
{
- lock (evaluator_lock){
- if (inited)
- return new string [0];
-
- 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 = new CompilerContext (settings, r) {
- IsEvalutor = true
- };
-
- RootContext.ToplevelTypes = module = new ModuleContainer (ctx);
-
- var startup_files = new List<string> ();
- foreach (CompilationUnit file in Location.SourceFiles)
- startup_files.Add (file.Path);
-
- CompilerCallableEntryPoint.PartialReset ();
+ var loader = new DynamicLoader (importer, ctx);
- var importer = new ReflectionImporter (module, ctx.BuildinTypes);
- loader = new DynamicLoader (importer, ctx);
+ CompilerCallableEntryPoint.Reset ();
+ RootContext.ToplevelTypes = module;
- module.SetDeclaringAssembly (new AssemblyDefinitionDynamic (module, "temp"));
+ //var startup_files = new List<string> ();
+ //foreach (CompilationUnit file in Location.SourceFiles)
+ // startup_files.Add (file.Path);
- loader.LoadReferences (module);
- ctx.BuildinTypes.CheckDefinitions (module);
- module.InitializePredefinedTypes ();
+ loader.LoadReferences (module);
+ ctx.BuildinTypes.CheckDefinitions (module);
+ module.InitializePredefinedTypes ();
- inited = true;
-
- return startup_files.ToArray ();
- }
+ inited = true;
}
- static void Init ()
- {
- Init (new string [0]);
- }
-
static void Reset ()
{
CompilerCallableEntryPoint.PartialReset ();
Location.AddFile (null, "{interactive}");
Location.Initialize ();
-
- current_debug_name = "interactive" + (count++) + ".dll";
}
+ /// <summary>
+ /// If true, turns type expressions into valid expressions
+ /// and calls the describe method on it
+ /// </summary>
+ public bool DescribeTypeExpressions;
+
/// <summary>
/// The base class for the classes that host the user generated code
/// </summary>
/// base class and the static members that are
/// available to your evaluated code.
/// </remarks>
- static public TypeSpec InteractiveBaseClass {
+ public Type InteractiveBaseClass {
get {
- if (interactive_base_class != null)
- return interactive_base_class;
-
- return loader.Importer.ImportType (typeof (InteractiveBase));
+ return base_class;
}
- }
-
- public static void SetInteractiveBaseClass (Type type)
- {
- if (type == null)
- throw new ArgumentNullException ();
-
- if (!inited)
- throw new Exception ("Evaluator has to be initiated before seting custom InteractiveBase class");
+ set {
+ base_class = value;
- lock (evaluator_lock)
- interactive_base_class = loader.Importer.ImportType (type);
+ if (value != null && typeof (InteractiveBase).IsAssignableFrom (value))
+ InteractiveBase.Evaluator = this;
+ }
}
/// <summary>
/// <remarks>
/// Use this method to interrupt long-running invocations.
/// </remarks>
- public static void Interrupt ()
+ public void Interrupt ()
{
if (!inited || !invoking)
return;
/// compiled parameter will be set to the delegate
/// that can be invoked to execute the code.
///
- /// </remarks>
- static public string Compile (string input, out CompiledMethod compiled)
+ /// </remarks>
+ public string Compile (string input, out CompiledMethod compiled)
{
if (input == null || input.Length == 0){
compiled = null;
return null;
}
-#if STATIC
- throw new NotSupportedException ();
-#else
Class parser_result = parser.InteractiveResult;
compiled = CompileBlock (parser_result, parser.undo, ctx.Report);
return null;
-#endif
}
}
/// On success, a delegate is returned that can be used
/// to invoke the method.
///
- /// </remarks>
- static public CompiledMethod Compile (string input)
+ /// </remarks>
+ public CompiledMethod Compile (string input)
{
CompiledMethod compiled;
return compiled;
}
- //
- // Todo: Should we handle errors, or expect the calling code to setup
- // the recording themselves?
- //
-
/// <summary>
/// Evaluates and expression or statement and returns any result values.
/// </summary>
/// that the input is partial and that the user
/// should provide an updated string.
/// </remarks>
- public static string Evaluate (string input, out object result, out bool result_set)
+ public string Evaluate (string input, out object result, out bool result_set)
{
CompiledMethod compiled;
//
// The code execution does not need to keep the compiler lock
//
- object retval = typeof (NoValueSet);
+ object retval = typeof (QuitValue);
try {
invoke_thread = System.Threading.Thread.CurrentThread;
// We use a reference to a compiler type, in this case
// Driver as a flag to indicate that this was a statement
//
- if (retval != typeof (NoValueSet)){
+ if (!ReferenceEquals (retval, typeof (QuitValue))) {
result_set = true;
result = retval;
}
return null;
}
- public static string [] GetCompletions (string input, out string prefix)
+ public string [] GetCompletions (string input, out string prefix)
{
prefix = "";
if (input == null || input.Length == 0)
Class parser_result = parser.InteractiveResult;
- try {
- var a = new AssemblyDefinitionDynamic (module, "temp");
- a.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.Run);
- module.SetDeclaringAssembly (a);
- module.CreateType ();
- module.Define ();
-
- parser_result.CreateType ();
- parser_result.Define ();
- if (ctx.Report.Errors != 0)
- return null;
-
- MethodOrOperator method = null;
- foreach (MemberCore member in parser_result.Methods){
- if (member.Name != "Host")
- continue;
-
- method = (MethodOrOperator) member;
- break;
- }
- if (method == null)
- throw new InternalErrorException ("did not find the the Host method");
+#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);
- BlockContext bc = new BlockContext (method, method.Block, method.ReturnType);
+ // Need to setup MemberCache
+ parser_result.CreateType ();
- try {
- method.Block.Resolve (null, bc, method);
- } catch (CompletionResult cr){
- prefix = cr.BaseText;
- return cr.Result;
- }
- } finally {
- if (parser.undo != null)
- parser.undo.ExecuteUndo ();
- }
-
+ var method = parser_result.Methods[0] as Method;
+ BlockContext bc = new BlockContext (method, method.Block, TypeManager.void_type);
+
+ try {
+ method.Block.Resolve (null, bc, method);
+ } catch (CompletionResult cr) {
+ prefix = cr.BaseText;
+ return cr.Result;
+ }
}
return null;
}
/// on success, false on parsing errors. Exceptions
/// might be thrown by the called code.
/// </remarks>
- public static bool Run (string statement)
+ public bool Run (string statement)
{
- if (!inited)
- Init ();
-
object result;
bool result_set;
- bool ok = Evaluate (statement, out result, out result_set) == null;
-
- return ok;
+ return Evaluate (statement, out result, out result_set) == null;
}
/// <summary>
/// This method will throw an exception if there is a syntax error,
/// of if the provided input is not an expression but a statement.
/// </remarks>
- public static object Evaluate (string input)
+ public object Evaluate (string input)
{
object result;
bool result_set;
// without more than one lookahead token. There are very
// few ambiguities.
//
- static InputKind ToplevelOrStatement (SeekableStreamReader seekable)
+ InputKind ToplevelOrStatement (SeekableStreamReader seekable)
{
Tokenizer tokenizer = new Tokenizer (seekable, (CompilationUnit) Location.SourceFiles [0], ctx);
// @partial_input: if @silent is true, then it returns whether the
// parsed expression was partial, and more data is needed
//
- static CSharpParser ParseString (ParseMode mode, string input, out bool partial_input)
+ CSharpParser ParseString (ParseMode mode, string input, out bool partial_input)
{
partial_input = false;
Reset ();
- queued_fields.Clear ();
Tokenizer.LocatedToken.Initialize ();
Stream s = new MemoryStream (Encoding.Default.GetBytes (input));
ReportPrinter old_printer = null;
if ((mode == ParseMode.Silent || mode == ParseMode.GetCompletions) && CSharpParser.yacc_verbose_flag == 0)
- old_printer = SetPrinter (new StreamReportPrinter (TextWriter.Null));
+ old_printer = ctx.Report.SetPrinter (new StreamReportPrinter (TextWriter.Null));
try {
parser.parse ();
}
if (old_printer != null)
- SetPrinter (old_printer);
+ ctx.Report.SetPrinter (old_printer);
}
return parser;
}
- //
- // Queue all the fields that we use, as we need to then go from FieldBuilder to FieldInfo
- // or reflection gets confused (it basically gets confused, and variables override each
- // other).
- //
- static List<Field> queued_fields = new List<Field> ();
-
- //static ArrayList types = new ArrayList ();
-
- static volatile bool invoking;
-#if !STATIC
- static CompiledMethod CompileBlock (Class host, Undo undo, Report Report)
+ CompiledMethod CompileBlock (Class host, Undo undo, Report Report)
{
+ string current_debug_name = "eval-" + count + ".dll";
+ ++count;
+#if STATIC
+ throw new NotSupportedException ();
+#else
AssemblyDefinitionDynamic assembly;
AssemblyBuilderAccess access;
if (Environment.GetEnvironmentVariable ("SAVE") != null) {
access = AssemblyBuilderAccess.RunAndSave;
assembly = new AssemblyDefinitionDynamic (module, current_debug_name, current_debug_name);
- assembly.Importer = loader.Importer;
+ assembly.Importer = importer;
} else {
#if NET_4_0
access = AssemblyBuilderAccess.RunAndCollect;
assembly.Create (AppDomain.CurrentDomain, access);
+ Method expression_method;
if (host != null) {
+ var base_class_imported = importer.ImportType (base_class);
+ var baseclass_list = new List<FullNamedExpression> (1) {
+ new TypeExpression (base_class_imported, host.Location)
+ };
+
+ host.AddBasesForPart (host, baseclass_list);
+
host.CreateType ();
+ host.DefineType ();
host.Define ();
+
+ expression_method = (Method) host.Methods[0];
+ } else {
+ expression_method = null;
}
module.CreateType ();
return null;
}
- TypeBuilder tb = null;
- MethodBuilder mb = null;
-
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;
- }
-
- if (mb == null)
- throw new Exception ("Internal error: did not find the method builder for the generated method");
-
host.EmitType ();
}
// Unlike Mono, .NET requires that the MethodInfo is fetched, it cant
// work from MethodBuilders. Retarded, I know.
//
- var tt = 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);
-
- Tuple<FieldSpec, FieldInfo> old;
-
- // If a previous value was set, nullify it, so that we do
- // not leak memory
- if (fields.TryGetValue (field.Name, out old)) {
- if (old.Item1.MemberType.IsStruct) {
- //
- // TODO: Clear fields for structs
- //
- } else {
- try {
- old.Item2.SetValue (null, null);
- } catch {
+ var tt = assembly.Builder.GetType (host.TypeBuilder.Name);
+ var mi = tt.GetMethod (expression_method.Name);
+
+ if (host.Fields != null) {
+ //
+ // We need to then go from FieldBuilder to FieldInfo
+ // or reflection gets confused (it basically gets confused, and variables override each
+ // other).
+ //
+ foreach (Field field in host.Fields) {
+ var fi = tt.GetField (field.Name);
+
+ Tuple<FieldSpec, FieldInfo> old;
+
+ // If a previous value was set, nullify it, so that we do
+ // not leak memory
+ if (fields.TryGetValue (field.Name, out old)) {
+ if (old.Item1.MemberType.IsStruct) {
+ //
+ // TODO: Clear fields for structs
+ //
+ } else {
+ try {
+ old.Item2.SetValue (null, null);
+ } catch {
+ }
}
}
- fields [field.Name] = Tuple.Create (field.Spec, fi);
- } else {
- fields.Add (field.Name, Tuple.Create (field.Spec, fi));
+ fields[field.Name] = Tuple.Create (field.Spec, fi);
}
}
- queued_fields.Clear ();
return (CompiledMethod) System.Delegate.CreateDelegate (typeof (CompiledMethod), mi);
- }
#endif
+ }
/// <summary>
/// A sentinel value used to indicate that no value was
/// differentiate between a function not returning a
/// value and null.
/// </summary>
- public class NoValueSet {
- }
+ internal static class QuitValue { }
- static internal Tuple<FieldSpec, FieldInfo> LookupField (string name)
+ internal Tuple<FieldSpec, FieldInfo> LookupField (string name)
{
Tuple<FieldSpec, FieldInfo> fi;
fields.TryGetValue (name, out fi);
return fi;
}
- //
- // Puts the FieldBuilder into a queue of names that will be
- // registered. We can not register FieldBuilders directly
- // we need to fetch the FieldInfo after Reflection cooks the
- // types, or bad things happen (bad means: FieldBuilders behave
- // incorrectly across multiple assemblies, causing assignments to
- // invalid areas
- //
- // This also serves for the parser to register Field classes
- // that should be exposed as global variables
- //
- static internal void QueueField (Field f)
- {
- queued_fields.Add (f);
- }
-
static string Quote (string s)
{
if (s.IndexOf ('"') != -1)
return "\"" + s + "\"";
}
- static public string GetUsing ()
+ public string GetUsing ()
{
- lock (evaluator_lock){
- if (ns == null)
- return null;
+ if (ns == null)
+ return null;
- StringBuilder sb = new StringBuilder ();
- // TODO:
- //foreach (object x in ns.using_alias_list)
- // sb.AppendFormat ("using {0};\n", x);
+ StringBuilder sb = new StringBuilder ();
+ // 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 ();
+ foreach (var ue in ns.Usings) {
+ sb.AppendFormat ("using {0};", ue.ToString ());
+ sb.Append (Environment.NewLine);
}
+
+ return sb.ToString ();
}
- static internal ICollection<string> GetUsingList ()
+ internal ICollection<string> GetUsingList ()
{
var res = new List<string> ();
return res;
}
- static internal string [] GetVarNames ()
+ internal string [] GetVarNames ()
{
lock (evaluator_lock){
return new List<string> (fields.Keys).ToArray ();
}
}
- static public string GetVars ()
+ public string GetVars ()
{
lock (evaluator_lock){
StringBuilder sb = new StringBuilder ();
/// <summary>
/// Loads the given assembly and exposes the API to the user.
/// </summary>
- static public void LoadAssembly (string file)
+ public void LoadAssembly (string file)
{
+ var loader = new DynamicLoader (importer, ctx);
+ var assembly = loader.LoadAssemblyFile (file);
+ if (assembly == null)
+ return;
+
lock (evaluator_lock){
- var a = loader.LoadAssemblyFile (file);
- if (a != null)
- loader.Importer.ImportAssembly (a, module.GlobalRootNamespace);
+ importer.ImportAssembly (assembly, module.GlobalRootNamespace);
}
}
/// <summary>
/// Exposes the API of the given assembly to the Evaluator
/// </summary>
- static public void ReferenceAssembly (Assembly a)
+ public void ReferenceAssembly (Assembly a)
{
lock (evaluator_lock){
- loader.Importer.ImportAssembly (a, module.GlobalRootNamespace);
+ importer.ImportAssembly (a, module.GlobalRootNamespace);
}
}
-
- /// <summary>
- /// If true, turns type expressions into valid expressions
- /// and calls the describe method on it
- /// </summary>
- public static bool DescribeTypeExpressions;
}
/// Used to signal that the user has invoked the `quit' statement.
/// </summary>
public static bool QuitRequested;
+
+ public static Evaluator Evaluator;
/// <summary>
/// Shows all the variables defined so far.
Output.Write (Evaluator.GetUsing ());
Output.Flush ();
}
-
- public delegate void Simple ();
-
+
/// <summary>
/// Times the execution of the given delegate
/// </summary>
- static public TimeSpan Time (Simple a)
+ static public TimeSpan Time (Action a)
{
DateTime start = DateTime.Now;
a ();
return DateTime.Now - start;
}
-#if !STATIC
/// <summary>
/// Loads the assemblies from a package
/// </summary>
}
}
}
-#endif
-#if !STATIC
/// <summary>
/// Loads the assembly
/// </summary>
{
Output.WriteLine (fmt, args);
}
-#endif
/// <summary>
/// Returns a list of available static methods.
QuitRequested = true;
// To avoid print null at the exit
- return typeof (Evaluator.NoValueSet);
+ return typeof (Evaluator.QuitValue);
}
}
// A useful feature for the REPL: if we can resolve the expression
// as a type, Describe the type;
//
- if (Evaluator.DescribeTypeExpressions){
- var old_printer = Evaluator.SetPrinter (new StreamReportPrinter (TextWriter.Null));
- clone = clone.Resolve (ec);
- if (clone == null){
- clone = source.Clone (cc);
- clone = clone.Resolve (ec, ResolveFlags.Type);
- if (clone == null){
- Evaluator.SetPrinter (old_printer);
+ if (ec.Module.Evaluator.DescribeTypeExpressions){
+ var old_printer = ec.Report.SetPrinter (new SessionReportPrinter ());
+ try {
+ clone = clone.Resolve (ec);
+ if (clone == null) {
clone = source.Clone (cc);
- clone = clone.Resolve (ec);
- return null;
+ clone = clone.Resolve (ec, ResolveFlags.Type);
+ if (clone == null) {
+ clone = source.Clone (cc);
+ clone = clone.Resolve (ec);
+ return null;
+ }
+
+ Arguments args = new Arguments (1);
+ args.Add (new Argument (new TypeOf ((TypeExpr) clone, Location)));
+ source = new Invocation (new SimpleName ("Describe", Location), args).Resolve (ec);
}
-
- Arguments args = new Arguments (1);
- args.Add (new Argument (new TypeOf ((TypeExpr) clone, Location)));
- source = new Invocation (new SimpleName ("Describe", Location), args).Resolve (ec);
+ } finally {
+ ec.Report.SetPrinter (old_printer);
}
- Evaluator.SetPrinter (old_printer);
} else {
clone = clone.Resolve (ec);
if (clone == null)
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{0831DD4E-B428-4D6C-90B1-2206DBD4F92E}</ProjectGuid>
- <OutputType>Exe</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>csharp</RootNamespace>
- <AssemblyName>csharp</AssemblyName>
- <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>TRACE;DEBUG;ON_DOTNET</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core">
- <RequiredTargetFramework>3.5</RequiredTargetFramework>
- </Reference>
- </ItemGroup>
- <ItemGroup>
- <Compile Include="..\..\class\corlib\Mono\DataConverter.cs">
- <Link>DataConverter.cs</Link>
- </Compile>
- <Compile Include="getline.cs" />
- <Compile Include="repl.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\class\Mono.CSharp\Mono.CSharp.csproj">
- <Project>{817CE046-07E8-409D-84BF-A6EA4F2879DE}</Project>
- <Name>Mono.CSharp</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+ <PropertyGroup>\r
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>\r
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>\r
+ <ProductVersion>9.0.30729</ProductVersion>\r
+ <SchemaVersion>2.0</SchemaVersion>\r
+ <ProjectGuid>{0831DD4E-B428-4D6C-90B1-2206DBD4F92E}</ProjectGuid>\r
+ <OutputType>Exe</OutputType>\r
+ <AppDesignerFolder>Properties</AppDesignerFolder>\r
+ <RootNamespace>csharp</RootNamespace>\r
+ <AssemblyName>csharp</AssemblyName>\r
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>\r
+ <FileAlignment>512</FileAlignment>\r
+ <FileUpgradeFlags>\r
+ </FileUpgradeFlags>\r
+ <OldToolsVersion>3.5</OldToolsVersion>\r
+ <UpgradeBackupLocation />\r
+ <PublishUrl>publish\</PublishUrl>\r
+ <Install>true</Install>\r
+ <InstallFrom>Disk</InstallFrom>\r
+ <UpdateEnabled>false</UpdateEnabled>\r
+ <UpdateMode>Foreground</UpdateMode>\r
+ <UpdateInterval>7</UpdateInterval>\r
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>\r
+ <UpdatePeriodically>false</UpdatePeriodically>\r
+ <UpdateRequired>false</UpdateRequired>\r
+ <MapFileExtensions>true</MapFileExtensions>\r
+ <ApplicationRevision>0</ApplicationRevision>\r
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>\r
+ <IsWebBootstrapper>false</IsWebBootstrapper>\r
+ <UseApplicationTrust>false</UseApplicationTrust>\r
+ <BootstrapperEnabled>true</BootstrapperEnabled>\r
+ <TargetFrameworkProfile />\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+ <DebugSymbols>true</DebugSymbols>\r
+ <DebugType>full</DebugType>\r
+ <Optimize>false</Optimize>\r
+ <OutputPath>bin\Debug\</OutputPath>\r
+ <DefineConstants>TRACE;DEBUG;ON_DOTNET</DefineConstants>\r
+ <ErrorReport>prompt</ErrorReport>\r
+ <WarningLevel>4</WarningLevel>\r
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+ <DebugType>pdbonly</DebugType>\r
+ <Optimize>true</Optimize>\r
+ <OutputPath>bin\Release\</OutputPath>\r
+ <DefineConstants>TRACE</DefineConstants>\r
+ <ErrorReport>prompt</ErrorReport>\r
+ <WarningLevel>4</WarningLevel>\r
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>\r
+ </PropertyGroup>\r
+ <ItemGroup>\r
+ <Reference Include="System" />\r
+ <Reference Include="System.Core">\r
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>\r
+ </Reference>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <Compile Include="..\..\class\corlib\Mono\DataConverter.cs">\r
+ <Link>DataConverter.cs</Link>\r
+ </Compile>\r
+ <Compile Include="getline.cs" />\r
+ <Compile Include="repl.cs" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <ProjectReference Include="..\..\class\Mono.CSharp\Mono.CSharp.csproj">\r
+ <Project>{817CE046-07E8-409D-84BF-A6EA4F2879DE}</Project>\r
+ <Name>Mono.CSharp</Name>\r
+ </ProjectReference>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <Folder Include="Properties\" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">\r
+ <Visible>False</Visible>\r
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>\r
+ <Install>false</Install>\r
+ </BootstrapperPackage>\r
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">\r
+ <Visible>False</Visible>\r
+ <ProductName>.NET Framework 3.5 SP1</ProductName>\r
+ <Install>true</Install>\r
+ </BootstrapperPackage>\r
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">\r
+ <Visible>False</Visible>\r
+ <ProductName>Windows Installer 3.1</ProductName>\r
+ <Install>true</Install>\r
+ </BootstrapperPackage>\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <None Include="app.config" />\r
+ </ItemGroup>\r
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />\r
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
- -->
+ -->\r
</Project>
\ No newline at end of file
public class Driver {
public static string StartupEvalExpression;
+ static int? attach;
+ static string agent;
static int Main (string [] args)
{
-#if !ON_DOTNET
- if (args.Length > 0 && args [0] == "--attach") {
- new ClientCSharpShell (Int32.Parse (args [1])).Run (null);
- return 0;
- }
+ var r = new Report (new ConsoleReportPrinter ());
+ var cmd = new CommandLineParser (r);
+ cmd.UnknownOptionHandler += HandleExtraArguments;
- if (args.Length > 0 && args [0].StartsWith ("--agent:")) {
- new CSharpAgent (args [0]);
- return 0;
- }
-#endif
- return Startup(args);
- }
+ var settings = cmd.ParseArguments (args);
+ if (settings == null || r.Errors > 0)
+ return 1;
- static int Startup (string[] args)
- {
- string[] startup_files;
+ var eval = new Evaluator (settings, r);
+
+ eval.InteractiveBaseClass = typeof (InteractiveBaseShell);
+ eval.DescribeTypeExpressions = true;
+
+ string[] startup_files = { };
+ /*
try {
startup_files = Evaluator.InitAndGetStartupFiles (args, HandleExtraArguments);
Evaluator.DescribeTypeExpressions = true;
} catch {
return 1;
}
- return new CSharpShell ().Run (startup_files);
+ */
+
+ CSharpShell shell;
+#if !ON_DOTNET
+ if (attach.HasValue) {
+ shell = new ClientCSharpShell (eval, attach.Value);
+ } else if (agent != null) {
+ new CSharpAgent (eval, agent).Run (startup_files);
+ return 0;
+ } else
+#endif
+ {
+ shell = new CSharpShell (eval);
+ }
+
+ return shell.Run (startup_files);
}
static int HandleExtraArguments (string [] args, int pos)
{
- if (args [pos] == "-e" && pos+1 < args.Length){
- StartupEvalExpression = args [pos+1];
- return pos+1;
+ switch (args [pos]) {
+ case "-e":
+ if (pos + 1 < args.Length) {
+ StartupEvalExpression = args[pos + 1];
+ return pos + 1;
+ }
+ break;
+ case "--attach":
+ if (pos + 1 < args.Length) {
+ attach = Int32.Parse (args[1]);
+ return pos + 1;
+ }
+ break;
+ case "--agent:":
+ agent = args[pos];
+ return pos + 1;
}
+
return -1;
}
Mono.Terminal.LineEditor editor;
bool dumb;
+ readonly Evaluator evaluator;
+
+ public CSharpShell (Evaluator evaluator)
+ {
+ this.evaluator = evaluator;
+ }
protected virtual void ConsoleInterrupt (object sender, ConsoleCancelEventArgs a)
{
// Do not about our program
a.Cancel = true;
- Mono.CSharp.Evaluator.Interrupt ();
+ evaluator.Interrupt ();
}
void SetupConsole ()
string complete = s.Substring (0, pos);
- string [] completions = Evaluator.GetCompletions (complete, out prefix);
+ string [] completions = evaluator.GetCompletions (complete, out prefix);
return new Mono.Terminal.LineEditor.Completion (prefix, completions);
};
}
foreach (string file in libraries)
- Evaluator.LoadAssembly (file);
+ evaluator.LoadAssembly (file);
ExecuteSources (sources, true);
}
object result;
try {
- input = Evaluator.Evaluate (input, out result, out result_set);
+ input = evaluator.Evaluate (input, out result, out result_set);
if (result_set){
PrettyPrint (Console.Out, result);
}
}
- public CSharpShell ()
- {
- }
-
public virtual int Run (string [] startup_files)
{
this.startup_files = startup_files;
class ClientCSharpShell : CSharpShell {
NetworkStream ns, interrupt_stream;
- public ClientCSharpShell (int pid)
+ public ClientCSharpShell (Evaluator evaluator, int pid)
+ : base (evaluator)
{
// Create a server socket we listen on whose address is passed to the agent
TcpListener listener = new TcpListener (new IPEndPoint (IPAddress.Loopback, 0));
class CSharpAgent
{
NetworkStream interrupt_stream;
+ readonly Evaluator evaluator;
- public CSharpAgent (String arg)
+ public CSharpAgent (Evaluator evaluator, String arg)
{
+ this.evaluator = evaluator;
new Thread (new ParameterizedThreadStart (Run)).Start (arg);
}
int b = interrupt_stream.ReadByte();
if (b == -1)
return;
- Evaluator.Interrupt ();
+ evaluator.Interrupt ();
interrupt_stream.WriteByte (0);
}
}
interrupt_stream = interrupt_client.GetStream ();
new Thread (InterruptListener).Start ();
- try {
- Evaluator.Init (new string [0]);
- } catch {
- // TODO: send a result back.
- Console.WriteLine ("csharp-agent: initialization failed");
- return;
- }
-
try {
// Add all assemblies loaded later
AppDomain.CurrentDomain.AssemblyLoad += AssemblyLoaded;
// Add all currently loaded assemblies
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies ())
- Evaluator.ReferenceAssembly (a);
+ evaluator.ReferenceAssembly (a);
RunRepl (s);
} finally {
}
}
- static void AssemblyLoaded (object sender, AssemblyLoadEventArgs e)
+ void AssemblyLoaded (object sender, AssemblyLoadEventArgs e)
{
- Evaluator.ReferenceAssembly (e.LoadedAssembly);
+ evaluator.ReferenceAssembly (e.LoadedAssembly);
}
public void RunRepl (NetworkStream s)
input = input + "\n" + line;
try {
- input = Evaluator.Evaluate (input, out result, out result_set);
+ input = evaluator.Evaluate (input, out result, out result_set);
} catch (Exception e) {
s.WriteByte ((byte) AgentStatus.ERROR);
s.WriteString (e.ToString ());