using System; using System.IO; using System.Text.RegularExpressions; using NAnt.Core.Attributes; using NAnt.Core.Types; using NAnt.DotNet.Tasks; namespace Nemerle.Tools.NAntTasks { /// /// Compiles Nemerle programs. /// [TaskName ("ncc")] public class NccTask : CompilerBase { private static _classNameRegex : Regex = Regex (@"^((?/\*.*?(\*/|$))|[\s\.\{]+|class\s+(?\w+)|(?\w+))*"); private static _namespaceRegex : Regex = Regex (@"^((?/\*.*?(\*/|$))|[\s\.\{]+|namespace\s+(?(\w+(\.\w+)*)+)|(?\w+))*"); /// /// Initialize new instance of the . /// public this () { SupportsKeyFile = true; } private static FindExecutable (toolName : string) : string { def my_file = Uri (typeof (NccTask).Assembly.EscapedCodeBase).LocalPath; def ncc_file = Path.Combine (Path.GetDirectoryName (my_file), toolName); if (File.Exists (ncc_file)) { // The tool found in the same folder. // ncc_file; } else { // Query the shell association. // def regPath = $@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\$toolName.exe"; def regKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (regPath); if (regKey != null) { // The tool is registered with the Shell API. // regKey.GetValue (null) :> string; } else { // Return the tool name itself. // The environment will search common paths for the tool. // toolName; } } } /// /// The name of the executable that should be used to launch the /// external program. /// /// /// The name of the executable that should be used to launch the external /// program, or if no name is specified. /// /// /// If available, the configured value in the NAnt configuration /// file will be used if no name is specified. /// public override ExeName : string { get { when (base.ExeName == Name) base.ExeName = FindExecutable (Name); base.ExeName; } set { base.ExeName = value; } } /// /// Gets the class name regular expression for the language of the /// current compiler. /// /// /// Class name regular expression for the language of the current /// compiler. /// protected override ClassNameRegex : Regex { get { _classNameRegex; } } /// /// Gets the namespace regular expression for the language of the /// current compiler. /// /// /// Namespace regular expression for the language of the current /// compiler. /// protected override NamespaceRegex : Regex { get { _namespaceRegex; } } /// /// Gets the command-line arguments for the external program. /// /// /// The command-line arguments for the external program. /// public override ProgramArguments : string { // quoting is done in CompilerBase // get { "-from-file:" + base.ProgramArguments.Substring (1); } } /// /// Writes an option using the default output format. /// /// The to which the compiler options should be written. /// The name of the option which should be passed to the compiler. protected override WriteOption (writer : TextWriter, name : string) : void { writer.WriteLine ("-{0}", name); } /// /// Writes an option and its value using the default output format. /// /// The to which the compiler options should be written. /// The name of the option which should be passed to the compiler. /// The value of the option which should be passed to the compiler. /// /// The combination of and /// (separated by a colon) is quoted /// unless is already surrounded by quotes. /// protected override WriteOption (writer : TextWriter, name : string, arg : string) : void { writer.WriteLine ((if (arg.StartsWith ("\"") && arg.EndsWith ("\"")) "-{0}:{1}" else "\"-{0}:{1}\""), name, arg); } /// /// Writes the compiler options to the specified . /// /// /// to which the compiler options should be written. protected override WriteOptions (writer : TextWriter) : void { when (DocFile != null) { WriteOption (writer, "xml", DocFile.FullName); } when (Debug) { WriteOption (writer, "debug"); WriteOption (writer, "def", "DEBUG"); WriteOption (writer, "def", "TRACE"); } when (NoStdLib) { WriteOption (writer, "nostdlib"); WriteOption (writer, "nostdmacros"); } when (Optimize) { WriteOption (writer, "Ot"); } WriteOption (writer, "greedy-"); WriteOption (writer, "no-color"); WriteOption (writer, "bar-"); } /// /// Determines whether compilation is needed. /// protected override NeedsCompiling () : bool { (DocFile != null && FileSet.FindMoreRecentLastWriteTime ( DocFile.FullName, OutputFile.LastWriteTime) != null) || base.NeedsCompiling (); } /// /// Gets the file extension required by the current compiler. /// /// /// For the Nemerle compiler, the file extension is always n. /// public override Extension : string { get { "n"; } } /// /// The name of the XML documentation file to generate. /// /// /// /// Corresponds with the -doc: flag. /// /// [TaskAttribute ("doc")] public DocFile : FileInfo { get; set; } /// /// Instructs the compiler not to import mscorlib.dll. The default is /// . /// /// /// /// Corresponds with the -nostdlib flag. /// /// [TaskAttribute ("nostdlib")] [BooleanValidator] public NoStdLib : bool { get; set; } /// /// Specifies whether the compiler should perform tail call optimizations /// to make output files smaller, faster, and more effecient. The default /// is . /// /// /// if the compiler should perform optimizations; /// otherwise, . /// /// /// /// Corresponds with the -general-tail-call-opt flag. /// /// [TaskAttribute ("optimize")] [BooleanValidator] public Optimize : bool { get; set; } } }