//
using System;
using System.Threading;
-using System.Collections;
+using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.IO;
static string current_debug_name;
static int count;
static Thread invoke_thread;
-
- static ArrayList using_alias_list = new ArrayList ();
- internal static ArrayList using_list = new ArrayList ();
- static Hashtable fields = new Hashtable ();
+
+ 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, FieldInfo> fields = new Dictionary<string, FieldInfo> ();
static Type interactive_base_class = typeof (InteractiveBase);
static Driver driver;
static bool inited;
+ static CompilerContext ctx;
+
+ public static TextWriter MessageOutput = Console.Out;
+
/// <summary>
/// Optional initialization for the Evaluator.
/// </summary>
InitAndGetStartupFiles (args);
}
-
+ internal static ReportPrinter SetPrinter (ReportPrinter report_printer)
+ {
+ return ctx.Report.SetPrinter (report_printer);
+ }
+
/// <summary>
/// Optional initialization for the Evaluator.
/// </summary>
if (inited)
return new string [0];
- driver = Driver.Create (args, false);
+ driver = Driver.Create (args, false, new ConsoleReportPrinter ());
if (driver == null)
throw new Exception ("Failed to create compiler driver with the given arguments");
+
+ RootContext.ToplevelTypes = new ModuleCompiled (ctx, true);
driver.ProcessDefaultConfig ();
- ArrayList startup_files = new ArrayList ();
+ var startup_files = new List<string> ();
foreach (CompilationUnit file in Location.SourceFiles)
startup_files.Add (file.Path);
CompilerCallableEntryPoint.Reset ();
+ RootContext.ToplevelTypes = new ModuleCompiled (ctx, true);
+
driver.LoadReferences ();
RootContext.EvalMode = true;
inited = true;
- return (string []) startup_files.ToArray (typeof (string));
+ return startup_files.ToArray ();
}
}
static void Reset ()
{
CompilerCallableEntryPoint.PartialReset ();
+
+ // Workaround for API limitation where full message printer cannot be passed
+ ReportPrinter printer;
+ if (MessageOutput == Console.Out || MessageOutput == Console.Error){
+ var console_reporter = new ConsoleReportPrinter (MessageOutput);
+ console_reporter.Fatal = driver.fatal_errors;
+ printer = console_reporter;
+ } else
+ printer = new StreamReportPrinter (MessageOutput);
+
+ ctx = new CompilerContext (new Report (printer));
+ RootContext.ToplevelTypes = new ModuleCompiled (ctx, true);
//
// PartialReset should not reset the core types, this is very redundant.
//
- if (!TypeManager.InitCoreTypes ())
+ if (!TypeManager.InitCoreTypes (ctx))
throw new Exception ("Failed to InitCoreTypes");
- TypeManager.InitOptionalCoreTypes ();
+ TypeManager.InitOptionalCoreTypes (ctx);
- Location.AddFile ("{interactive}");
+ Location.AddFile (null, "{interactive}");
Location.Initialize ();
current_debug_name = "interactive" + (count++) + ".dll";
if (Environment.GetEnvironmentVariable ("SAVE") != null){
- CodeGen.Init (current_debug_name, current_debug_name, false);
+ CodeGen.Init (current_debug_name, current_debug_name, false, ctx);
} else
- CodeGen.InitDynamic (current_debug_name);
+ CodeGen.InitDynamic (ctx, current_debug_name);
}
/// <summary>
object parser_result = parser.InteractiveResult;
if (!(parser_result is Class)){
- int errors = Report.Errors;
+ int errors = ctx.Report.Errors;
NamespaceEntry.VerifyAllUsing ();
- if (errors == Report.Errors)
+ if (errors == ctx.Report.Errors)
parser.CurrentNamespace.Extract (using_alias_list, using_list);
}
- compiled = CompileBlock (parser_result as Class, parser.undo);
+ compiled = CompileBlock (parser_result as Class, parser.undo, ctx.Report);
}
return null;
// Either null (on error) or the compiled method.
return compiled;
}
-
+
//
// Todo: Should we handle errors, or expect the calling code to setup
// the recording themselves?
// The code execution does not need to keep the compiler lock
//
object retval = typeof (NoValueSet);
-
+
try {
invoke_thread = System.Threading.Thread.CurrentThread;
invoking = true;
try {
RootContext.ResolveTree ();
- if (Report.Errors != 0)
+ if (ctx.Report.Errors != 0)
return null;
RootContext.PopulateTypes ();
- if (Report.Errors != 0)
+ if (ctx.Report.Errors != 0)
return null;
MethodOrOperator method = null;
if (method == null)
throw new InternalErrorException ("did not find the the Host method");
- EmitContext ec = method.CreateEmitContext (method.Parent, null);
- bool unreach;
+ BlockContext bc = new BlockContext (method, method.Block, method.ReturnType);
try {
- ec.ResolveTopBlock (null, method.Block, method.ParameterInfo, method, out unreach);
+ method.Block.Resolve (null, bc, method.ParameterInfo, method);
} catch (CompletionResult cr){
prefix = cr.BaseText;
return cr.Result;
- }
+ }
} finally {
parser.undo.ExecuteUndo ();
}
//
static InputKind ToplevelOrStatement (SeekableStreamReader seekable)
{
- Tokenizer tokenizer = new Tokenizer (seekable, (CompilationUnit) Location.SourceFiles [0]);
+ Tokenizer tokenizer = new Tokenizer (seekable, (CompilationUnit) Location.SourceFiles [0], ctx);
int t = tokenizer.token ();
switch (t){
partial_input = false;
Reset ();
queued_fields.Clear ();
+ Tokenizer.LocatedToken.Initialize ();
Stream s = new MemoryStream (Encoding.Default.GetBytes (input));
SeekableStreamReader seekable = new SeekableStreamReader (s, Encoding.Default);
InputKind kind = ToplevelOrStatement (seekable);
if (kind == InputKind.Error){
if (mode == ParseMode.ReportErrors)
- Report.Error (-25, "Detection Parsing Error");
+ ctx.Report.Error (-25, "Detection Parsing Error");
partial_input = false;
return null;
}
}
seekable.Position = 0;
- CSharpParser parser = new CSharpParser (seekable, (CompilationUnit) Location.SourceFiles [0]);
- parser.ErrorOutput = Report.Stderr;
+ CSharpParser parser = new CSharpParser (seekable, (CompilationUnit) Location.SourceFiles [0], ctx);
if (kind == InputKind.StatementOrExpression){
parser.Lexer.putback_char = Tokenizer.EvalStatementParserCharacter;
if (mode == ParseMode.GetCompletions)
parser.Lexer.CompleteOnEOF = true;
- bool disable_error_reporting;
+ ReportPrinter old_printer = null;
if ((mode == ParseMode.Silent || mode == ParseMode.GetCompletions) && CSharpParser.yacc_verbose_flag == 0)
- disable_error_reporting = true;
- else
- disable_error_reporting = false;
-
- if (disable_error_reporting)
- Report.DisableReporting ();
+ old_printer = SetPrinter (new StreamReportPrinter (TextWriter.Null));
+
try {
parser.parse ();
} finally {
- if (Report.Errors != 0){
+ if (ctx.Report.Errors != 0){
if (mode != ParseMode.ReportErrors && parser.UnexpectedEOF)
partial_input = true;
parser = null;
}
- if (disable_error_reporting)
- Report.EnableReporting ();
+ if (old_printer != null)
+ SetPrinter (old_printer);
}
return parser;
}
// or reflection gets confused (it basically gets confused, and variables override each
// other).
//
- static ArrayList queued_fields = new ArrayList ();
+ static List<Field> queued_fields = new List<Field> ();
//static ArrayList types = new ArrayList ();
static volatile bool invoking;
- static CompiledMethod CompileBlock (Class host, Undo undo)
+ static CompiledMethod CompileBlock (Class host, Undo undo, Report Report)
{
RootContext.ResolveTree ();
if (Report.Errors != 0){
}
RootContext.EmitCode ();
- if (Report.Errors != 0)
+ if (Report.Errors != 0){
+ undo.ExecuteUndo ();
return null;
+ }
RootContext.CloseTypes ();
if (Environment.GetEnvironmentVariable ("SAVE") != null)
- CodeGen.Save (current_debug_name, false);
+ CodeGen.Save (current_debug_name, false, Report);
if (host == null)
return null;
foreach (Field field in queued_fields){
FieldInfo fi = tt.GetField (field.Name);
- FieldInfo old = (FieldInfo) fields [field.Name];
+ FieldInfo old;
// If a previous value was set, nullify it, so that we do
// not leak memory
- if (old != null){
+ if (fields.TryGetValue (field.Name, out old)){
if (TypeManager.IsStruct (old.FieldType)){
//
// TODO: Clear fields for structs
static internal FieldInfo LookupField (string name)
{
- FieldInfo fi = (FieldInfo) fields [name];
+ FieldInfo fi;
+ if (!fields.TryGetValue (name, out fi))
+ return null;
return fi;
}
}
}
- static internal ICollection GetUsingList ()
+ static internal ICollection<string> GetUsingList ()
{
- ArrayList res = new ArrayList (using_list.Count);
+ var res = new List<string> (using_list.Count);
foreach (object ue in using_list)
res.Add (ue.ToString ());
return res;
static internal string [] GetVarNames ()
{
lock (evaluator_lock){
- return (string []) new ArrayList (fields.Keys).ToArray (typeof (string));
+ return new List<string> (fields.Keys).ToArray ();
}
}
lock (evaluator_lock){
StringBuilder sb = new StringBuilder ();
- foreach (DictionaryEntry de in fields){
- FieldInfo fi = LookupField ((string) de.Key);
+ foreach (var de in fields){
+ FieldInfo fi = LookupField (de.Key);
object value = null;
bool error = false;
static public void LoadAssembly (string file)
{
lock (evaluator_lock){
- Driver.LoadAssembly (file, false);
- GlobalRootNamespace.Instance.ComputeNamespaces ();
+ driver.LoadAssembly (file, false);
+ GlobalRootNamespace.Instance.ComputeNamespaces (ctx);
}
}
{
lock (evaluator_lock){
GlobalRootNamespace.Instance.AddAssemblyReference (a);
- GlobalRootNamespace.Instance.ComputeNamespaces ();
+ GlobalRootNamespace.Instance.ComputeNamespaces (ctx);
}
}
-
+
+ /// <summary>
+ /// If true, turns type expressions into valid expressions
+ /// and calls the describe method on it
+ /// </summary>
+ public static bool DescribeTypeExpressions;
}
return;
}
- string pkgout = Driver.GetPackageFlags (pkg, false);
+ string pkgout = Driver.GetPackageFlags (pkg, false, RootContext.ToplevelTypes.Compiler.Report);
if (pkgout == null)
return;
return name.GetHashCode ();
}
- override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
{
Expression ret = base.DoResolveLValue (ec, right_side);
if (ret == null)
{
}
- public override Expression DoResolve (EmitContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
{
CloneContext cc = new CloneContext ();
Expression clone = source.Clone (cc);
+ var old_printer = Evaluator.SetPrinter (new StreamReportPrinter (TextWriter.Null));
clone = clone.Resolve (ec);
- if (clone == null)
- return null;
+ if (clone == null){
+ //
+ // A useful feature for the REPL: if we can resolve the expression
+ // as a type, Describe the type;
+ //
+ if (Evaluator.DescribeTypeExpressions){
+ clone = source.Clone (cc);
+ clone = clone.Resolve (ec, ResolveFlags.Type);
+ if (clone == null){
+ Evaluator.SetPrinter (old_printer);
+ clone = source.Clone (cc);
+ clone = clone.Resolve (ec);
+ return null;
+ }
+ Arguments args = new Arguments (1);
+ args.Add (new Argument (new TypeOf (source, Location)));
+ source = new Invocation (new SimpleName ("Describe", Location), args).Resolve (ec);
+ } else {
+ Evaluator.SetPrinter (old_printer);
+ return null;
+ }
+ }
+ Evaluator.SetPrinter (old_printer);
+
// This means its really a statement.
if (clone.Type == TypeManager.void_type){
source = source.Resolve (ec);
}
public class Undo {
- ArrayList undo_types;
+ List<KeyValuePair<TypeContainer, TypeContainer>> undo_types;
public Undo ()
{
- undo_types = new ArrayList ();
+ undo_types = new List<KeyValuePair<TypeContainer, TypeContainer>> ();
}
public void AddTypeContainer (TypeContainer current_container, TypeContainer 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));
+ undo_types = new List<KeyValuePair<TypeContainer, TypeContainer>> ();
+
+ undo_types.Add (new KeyValuePair<TypeContainer, TypeContainer> (current_container, tc));
}
public void ExecuteUndo ()
if (undo_types == null)
return;
- foreach (Pair p in undo_types){
- TypeContainer current_container = (TypeContainer) p.First;
+ foreach (var p in undo_types){
+ TypeContainer current_container = p.Key;
- current_container.RemoveTypeContainer ((TypeContainer) p.Second);
+ current_container.RemoveTypeContainer (p.Value);
}
undo_types = null;
}