/* * Copyright (c) 2003-2008 The University of Wroclaw. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the University may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE UNIVERSITY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using Nemerle.Collections; using Nemerle.Compiler.Parsetree; using Nemerle.Utility; using SCG = System.Collections.Generic; using TExpr = Nemerle.Compiler.Typedtree.TExpr; namespace Nemerle.Compiler { public class ManagerClass { public static mutable Instance : ManagerClass; public SystemTypeCache : SystemTypeClass; public InternalType : InternalTypeClass; internal AttributeCompiler : AttributeCompilerClass; internal Stats : StatsClass; internal mutable Solver : Solver; public GetSolver(): Solver {Solver} public CheckSolver() : void { unless (this.Solver.IsTopLevel) System.Diagnostics.Trace.WriteLine("this.Solver.IsTopLevel == false"); } public mutable Hierarchy : TypesManager; protected internal mutable LibrariesManager : LibraryReferenceManager; public mutable NameTree : NamespaceTree; public mutable CoreEnv : GlobalEnv; public mutable MacrosRegistry : MacroRegistry; public mutable Options : CompilationOptions; public mutable MacroColors : MacroColorizator; internal mutable emptyTEnv : TyVarEnv; [Accessor] componentsFactory : CompilerComponentsFactory; [Accessor (flags = WantSetter | Internal | Protected)] internal mutable doc_comments : Map [Location, string]; internal mutable tyinfo_counter : int; mutable current_tyinfo_count : int; mutable current_pb_stage : int; mutable pb_killed : bool; public delegate MessageEventHandler (loc : Location, msg : string) : void; public event ErrorOccured : MessageEventHandler; public event WarningOccured : MessageEventHandler; public event MessageOccured : MessageEventHandler; internal RunErrorOccured (loc : Location, msg : string) : void { when (ErrorOccured != null) ErrorOccured (loc, msg) } internal RunWarningOccured (loc : Location, msg : string) : void { when (WarningOccured != null) WarningOccured (loc, msg) } internal RunMessageOccured (loc : Location, msg : string) : void { when (MessageOccured != null) MessageOccured (loc, msg) } public InitOutput (o : System.IO.TextWriter) : void { Message_output = o; } #region ,,static'' data from other modules internal mutable StaticTyVarId : int; internal mutable Typer_DT_Id : int; internal Typer_BetterTypeCache : Hashtable [TypeInfo * TypeInfo, bool] = Hashtable (); internal mutable Typer_checked_macro : NamespaceTree.Node; internal mutable Typer_unchecked_macro : NamespaceTree.Node; internal mutable Typer_yield_macro : NamespaceTree.Node; internal mutable TyVar_reuse_queue : TyVar; internal mutable TyVar_Id : int; internal mutable Util_Id : int; internal mutable AttributeMacroExpansion_global_nr : int; internal mutable Macros_in_pattern : bool; internal mutable Message_error_cnt : int; internal mutable Message_warning_cnt : int; internal mutable Message_emitted_hints : Hashtable [string, int] = Hashtable (); protected internal mutable Message_output : System.IO.TextWriter; [Accessor] private mutable _locationStack : SCG.List.[Location] = SCG.List(32); //private mutable _locationStack : Vector [Location] = Vector (32); public CurrentLocation () : Location { Location_stack.top (this) } /** Called by parser when simple "using" directive parsed . * name : list [string] - qualified identifier/ * prevEnv : GlobalEnv - GlobalEnv before adding current using directive. * location : Location - location of qualified identifier. */ protected mutable _afterUsingDirectiveParse : Location * list [string] * list [Location] * string * Location * GlobalEnv * GlobalEnv -> void; internal OnAfterUsingDirectiveParse( location : Location, name : list [string], nameLocations : list [Location], alias : string, aliasLocation : Location, beforeEnv : GlobalEnv, afterEnv : GlobalEnv ) : void { when (_afterUsingDirectiveParse != null) _afterUsingDirectiveParse (location, name, nameLocations, alias, aliasLocation, beforeEnv, afterEnv); } protected mutable _beforeNamespaceParse : void -> void; internal OnBeforeNamespaceParse () : void { when (_beforeNamespaceParse != null) _beforeNamespaceParse (); } protected mutable _afterNamespaceParse : Location * list [string] * list [Location] * GlobalEnv * GlobalEnv * Location -> void; internal OnAfterNamespaceParse ( location : Location, name : list [string], nameLocations : list [Location], outsideEnv : GlobalEnv, insideEnv : GlobalEnv, bodyLocation : Location ) : void { when (_afterNamespaceParse != null) _afterNamespaceParse (location, name, nameLocations, outsideEnv, insideEnv, bodyLocation); } /// Clearing all variables used in typing process. /// Use this method only if we destroy NamespaceTree protected virtual FullResetNamespaceTree () : void { Hierarchy = null; Typer_checked_macro = null; Typer_unchecked_macro = null; Typer_yield_macro = null; Typer_BetterTypeCache.Clear (); StaticTyVarId = 0; Typer_DT_Id = 0; TyVar_Id = 0; TyVar_reuse_queue = null; Util_Id = 0; AttributeMacroExpansion_global_nr = 0; } #endregion /// initialize pipelines with default values public this (options : CompilationOptions) { Instance = this; assert (options != null); componentsFactory = CreateComponentsFactory (); ParsingPipeline = MainParser.Parse; def scanner = ScanTypeHierarchy (this); ScanningPipeline = scanner.ProcessDeclaration; this.Options = options; InternalType = InternalTypeClass (this); SystemTypeCache = SystemTypeClass (this); AttributeCompiler = AttributeCompilerClass (this); Stats = StatsClass (); } public MarkAsUsed (member : IMember) : void { MarkAsUsed (member, Location.Default, true); } public MarkAsUsed (member : IMember, trigger_obsolete_warn : bool) : void { MarkAsUsed (member, Location.Default, trigger_obsolete_warn); } public virtual MarkAsUsed (member : IMember, _location : Location, trigger_obsolete_warn : bool) : void { member.HasBeenUsed = trigger_obsolete_warn; } public virtual MarkAsAssigned (member : IField) : void { member.HasBeenAssigned = true; } public virtual MarkAsAssigned (member : IField, _location : Location, trigger_obsolete_warn : bool) : void { member.HasBeenAssigned = trigger_obsolete_warn; } protected virtual CreateComponentsFactory () : CompilerComponentsFactory { CompilerComponentsFactory () } // ---- PIPELINES USED IN COMPILATION PROCESS ---- /** Pipeline function for creating lexer object from given string. In default compilation it is a function creating LexerFile from given filename. It can be customized to do any other action, like treating given string as textual code and creating LexerString from it. */ public mutable LexingPipeline : string -> LexerBase; /** Pipeline for performing parsing of lexical tokens into parsetree. In default compilation it is using provided LexerFile object to parse tokens and build list of TopDeclarations */ public mutable ParsingPipeline : LexerBase -> list [TopDeclaration]; /** Pipeline for adding namespaces and types hierarchy from parsed declarations. The list of declarations denotes the scope of one file, including using statements, etc. So the default pipeline passes enriched environment through declarations on the list. */ public mutable ScanningPipeline : TopDeclaration -> void; public delegate InitDelegate () : void; public static event OnInit : InitDelegate; public GeneratedAssembly : System.Reflection.Assembly { get { Hierarchy.GeneratedAssembly } } internal MarkTypeBuilderCompiled () : void { current_tyinfo_count = current_tyinfo_count + 1; ProgressBar (10 + current_tyinfo_count * 90 / tyinfo_counter); } /// True if compiler runing in IntelliSense mode. This disable some /// optimisations and anable lazy methods bodies compilation. [Accessor] protected mutable _isIntelliSenseMode : bool = false; /// True if now completion word in progress. This enable additional checks /// of completion tokens. [Accessor] protected mutable _isCompletionInProgress : bool = false; ProgressBar (stage : int) : void { when (Options.ProgressBar) { def max = 60; def act = stage * max / 100; def act = if (act > max) max else act; def diff = act - current_pb_stage; when ((pb_killed && diff > 10) || (!pb_killed && diff > 0)) { System.Console.Write ("\r" + System.String ('_', act) + System.String ('.', max - act) + "\r"); current_pb_stage = act; pb_killed = false; } } } public KillProgressBar () : void { when (Options.ProgressBar && !pb_killed) { System.Console.Write ("\n"); pb_killed = true; } } protected shouldCreate (obj : object) : bool { !Options.PersistentLibraries || obj == null } CleanUp () : void { LexingPipeline = null; // so we can switch to other lexer when options change when (Hierarchy != null) Hierarchy.Dispose (); } protected InitCompiler () : void { Stats.Reset (); Message_emitted_hints.Clear (); Macros_in_pattern = false; Message_error_cnt = 0; Message_warning_cnt = 0; MacroColors = MacroColorizator (); if (shouldCreate (NameTree)) NameTree = NamespaceTree (this); else NameTree.Init (); when (shouldCreate (MacrosRegistry)) MacrosRegistry = MacroRegistry (this); when (shouldCreate (LibrariesManager)) LibrariesManager = ComponentsFactory.CreateLibraryReferenceManager (this, Options.LibraryPaths); Options.Validate (); this.Solver = Solver (this); this.emptyTEnv = TyVarEnv (this); if (Options.LexerStoreComments) DocComments = Map (); else DocComments = null; when (Hierarchy != null) Hierarchy.RemoveProgramTypes(); // if it was not initialized outside the Run when (LexingPipeline == null) if (Options.IndentationSyntax) LexingPipeline = fun (fn) { def lexer = LexerFile (this, fn); lexer.SwitchToIndentationMode (); lexer } else LexingPipeline = LexerFile (this, _); when (OnInit != null) OnInit (); // run externally registered functions - used for cleanup of macro_context_classes in used macros } protected internal LoadExternalLibraries () : void { if (shouldCreate (InternalType.Void)) { unless (Options.DoNotLoadStdlib) { LibrariesManager.AddLibrary ("mscorlib"); LibrariesManager.AddLibrary ("System"); LibrariesManager.AddLibrary ("Nemerle"); LibrariesManager.AddLibrary ("System.Xml"); }; foreach (lib in Options.ReferencedLibraries.Reverse()) LibrariesManager.AddLibrary (lib); LibrariesManager.LoadLibrariesContents (); foreach (file in Options.MacrosToLoad.Reverse()) LibrariesManager.LoadMacrosFrom (file); SystemTypeCache.Init (); InternalType.InitSystemTypes (); unless (Options.DoNotLoadStdlib) InternalType.InitNemerleTypes (); LibrariesManager.LoadExtensions (); unless (Options.DoNotLoadMacros) LoadNemerleMacros (); CoreEnv = GlobalEnv.CreateCore (NameTree); } else // We use LibrariesManager repeatedly. LibrariesManager.RemoveInternalExtensionMethods(); } protected virtual LoadNemerleMacros () : void { def version = typeof (ManagerClass).Assembly.GetName().Version.ToString (); LibrariesManager.LoadMacrosFrom ("Nemerle.Macros", ", Version="+version+", Culture=neutral, PublicKeyToken=5291d186334f6101"); } /** * Run passes of the compiler. */ public Run () : void { Instance = this; try { InitCompiler (); ProgressBar (1); LoadExternalLibraries (); ProgressBar (2); Hierarchy = TypesManager (this); def trees = List.RevMap (Options.Sources, fun (x) { ParsingPipeline (LexingPipeline (x)) }); Message.MaybeBailout(); // we have detected multiple files already ProgressBar (5); // create N.C.TypeBuilders for all parsed types and add them to namespace hierarchy foreach (group in trees) List.Iter (group, ScanningPipeline); when (Options.DoNotLoadStdlib) InternalType.InitNemerleTypes (); ProgressBar (8); Hierarchy.Run (); when (Message.SeenError) NameTree.CheckReferencedNamespaces (); Message.MaybeBailout(); Hierarchy.CreateAssembly (); ProgressBar (10); Hierarchy.EmitAuxDecls (); when (Message.SeenError) NameTree.CheckReferencedNamespaces (); Message.MaybeBailout(); NameTree.CheckReferencedNamespaces (); Hierarchy.EmitDecls (); Message.MaybeBailout(); NameTree.FinishMacroContextClass (); Hierarchy.CheckForUnusedGlobalSymbols (); Hierarchy.CheckFinalization (); when (Options.XmlDocOutputFileName != null) { def docs = XmlDoc (DocComments, Options.XmlDocOutputFileName); Hierarchy.SourceTopIter (docs.DumpType); docs.Save (); } unless (Options.CompileToMemory) Hierarchy.SaveAssembly (); Message.MaybeBailout(); KillProgressBar (); Stats.Run (this); } finally { CleanUp (); when (Options.PersistentLibraries) Hierarchy.RemoveProgramTypes(); } } public Lookup (type_name : string) : TypeInfo { match (NameTree.LookupExactType (type_name)) { | Some (t) => t | None => Util.ice ("internal type " + type_name + " not found") } } public Lookup (type_name : string, args_count : int) : TypeInfo { match (NameTree.LookupExactType (type_name, args_count)) { | Some (t) => t | None => Util.ice ("internal type " + type_name + " not found") } } /// Return true if 'method' is extension method. protected internal virtual IsExtensionMethod (method : IMethod, tyVar2 : TyVar) : bool { _= tyVar2; _ = method; throw System.NotImplementedException (); } /// Process completion. protected internal virtual Complete (expression : PExpr, expected : TyVar, typer : Typer, env : GlobalEnv) : TExpr { ignore (expression); ignore (expected); ignore (typer); ignore (env); throw System.NotImplementedException (); } /// Process completion in patterns. protected internal virtual CompletePattern ( expression : PExpr, matched_value_type : TyVar, patternTyper : Typer.PatternTyper, env : GlobalEnv ) : void { ignore (expression); ignore (matched_value_type); ignore (patternTyper); ignore (env); throw System.NotImplementedException (); } /// Process completion in type reference. protected internal virtual CompleteTypeRef ( expression : PExpr, curTypeBuilder : TypeBuilder, env : GlobalEnv ) : void { ignore (curTypeBuilder); ignore (env); match (expression) { | PExpr.ToComplete (name) with obj = null | PExpr.Member (obj, Parsetree.Splicable.HalfId (name)) => def obj = obj; def name = name; def elems = SCG.List (); def nss = this.CoreEnv.NameTree.NamespaceTree :: name.GetEnv(this.CoreEnv).OpenNamespaces; Completion.AddTypesAndNamespaces (elems, nss, obj, name, true); throw CompletionResult (elems, name.Id); | _ => () } } } }