private IEnumerable<FileInfo> _pathCandidates(RefSpec refSepc, CancellationToken token) { var resolvedPath = refSepc.ResolvedPath; if (resolvedPath != null) yield return resolvedPath; var prefixes = _copySearchPaths(token).Result; var rawPath = refSepc.RawPath; // Prefer a path, if one was provided. if (rawPath != null) { if (Path.IsPathRooted(rawPath)) { // Path is absolute, just try it yield return _safelyCreateFileInfo(rawPath); } else { // Path is relative. We won't try the process working directory unless // explicitly instructed to (by adding '.' to the search paths) foreach (var candidate in _combineWithSearchPaths(prefixes, rawPath)) yield return candidate; } } var moduleName = refSepc.ModuleName; if (moduleName != null) { var splitPrefix = moduleName.Id; while (true) // while there are '.' in the module name... { // ... try each search path in turn ... foreach (var candidate in _combineWithSearchPaths(prefixes, splitPrefix + ".pxs")) yield return candidate; // ... convert the last '.' to a '/' (or platform equivalent) ... var dotIndex = splitPrefix.LastIndexOf('.'); // Check if there is a '.' that is not the first (=0) or last character of the module name if (1 <= dotIndex && dotIndex <= splitPrefix.Length - 2) { splitPrefix = Path.Combine( splitPrefix.Substring(0, dotIndex), splitPrefix.Substring(dotIndex + 1)); } else { // ... or abort if all '.' have been converted ... break; } } } }
private async Task<PreflightResult> _performPreflight(RefSpec refSpec, CancellationToken token) // requires refSpec.Source != null // ensures result != null { if (refSpec.ErrorMessage != null) return new PreflightResult { ErrorMessage = refSpec.ErrorMessage }; token.ThrowIfCancellationRequested(); _trace.TraceEvent(TraceEventType.Information, 0, "Preflight parsing of {0} requested.", refSpec); // Make sure refSpec has a re-usable source (will have to support both preflight and actual compilation) var source = refSpec.Source; if (source == null) throw new ArgumentException(Resources.SelfAssemblingPlan_RefSpecMustHaveSource, "refSpec"); var reportedPath = _getPath(source); if (source.IsSingleUse) source = await source.CacheInMemoryAsync(); token.ThrowIfCancellationRequested(); // Perform preflight parse var eng = new Engine { ExecutionProhibited = true }; var app = new Application(); var ldr = new Loader(new LoaderOptions(eng, app) { // Important: Have preflight flag set PreflightModeEnabled = true, ReconstructSymbols = false, RegisterCommands = false, StoreSourceInformation = false, }); TextReader sourceReader; if (!source.TryOpen(out sourceReader)) { var errorResult = new PreflightResult { ErrorMessage = "Failed to open " + refSpec + " for preflight parsing." }; return errorResult; } ldr.LoadFromReader(sourceReader, refSpec.ResolvedPath != null ? refSpec.ResolvedPath.ToString() : null); // Extract preflight information ModuleName theModuleName; if (!ModuleName.TryParse(app.Meta[Module.NameKey], out theModuleName)) theModuleName = app.Module.Name; MetaEntry noStdLibEntry; var result = new PreflightResult { ModuleName = theModuleName, SuppressStandardLibrary = app.Meta.TryGetValue(Module.NoStandardLibraryKey, out noStdLibEntry) && noStdLibEntry.Switch, Path = reportedPath }; result.References.AddRange( app.Meta[Module.ReferencesKey].List.Where(entry => !entry.Equals(new MetaEntry(""))) .Select(_parseRefSpec)); _trace.TraceEvent(TraceEventType.Verbose, 0, "Preflight parsing of {0} finished.", refSpec); return result; }
private RefSpec _forbidFileRefSpec(RefSpec refSpec) { if (refSpec.ModuleName == null) refSpec.ErrorMessage = refSpec.ErrorMessage ?? Resources.SelfAssemblingPlan__forbidFileRefSpec_notallowed; return refSpec; }
private Task<PreflightResult> _orderPreflight(RefSpec refSpec, CancellationToken token) { if (refSpec.ResolvedPath == null) throw new ArgumentException(Resources.SelfAssemblingPlan_RefSepcMustHaveResolvedPathForPreflightOrder, "refSpec"); return _preflightCache.GetOrAdd(refSpec.ResolvedPath.FullName, async (path, actualToken) => { refSpec.Source = new FileSource(refSpec.ResolvedPath, Encoding); await Task.Yield(); // Need to yield at this point to keep // the critical section of the cache short return await _performPreflight(refSpec, actualToken); }, token); }