diff --git a/src/absil/illib.fs b/src/absil/illib.fs index ef71ec8df8f..047ff65b41a 100644 --- a/src/absil/illib.fs +++ b/src/absil/illib.fs @@ -240,7 +240,12 @@ module Array = /// Returns true if one array has trailing elements equal to another's. let endsWith (suffix: _ []) (whole: _ []) = isSubArray suffix whole (whole.Length-suffix.Length) - + + let unzip4 (array: _ []) = + let a, b, cd = Array.unzip3 (Array.map (fun (x, y, z, w) -> (x, y, (z, w))) array) + let c, d = Array.unzip cd + a, b, c, d + module Option = let mapFold f s opt = diff --git a/src/fsharp/CompileOps.fs b/src/fsharp/CompileOps.fs index 1ae2d315076..508b152fba5 100644 --- a/src/fsharp/CompileOps.fs +++ b/src/fsharp/CompileOps.fs @@ -2103,7 +2103,7 @@ type TcConfigBuilder = mutable implicitlyResolveAssemblies: bool mutable light: bool option mutable conditionalCompilationDefines: string list - mutable loadedSources: (range * string * string) list + mutable loadedSources: (range * string * string)[] mutable compilerToolPaths: string list mutable referencedDLLs: AssemblyReference list mutable packageManagerLines: Map @@ -2274,7 +2274,7 @@ type TcConfigBuilder = packageManagerLines = Map.empty projectReferences = [] knownUnresolvedReferences = [] - loadedSources = [] + loadedSources = Array.Empty() errorSeverityOptions = FSharpErrorSeverityOptions.Default embedResources = [] inputCodePage = None @@ -2437,17 +2437,30 @@ type TcConfigBuilder = /// Decide names of output file, pdb and assembly member tcConfigB.DecideNames (sourceFiles) = use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter - if sourceFiles = [] then errorR(Error(FSComp.SR.buildNoInputsSpecified(), rangeCmdArgs)) - let ext() = match tcConfigB.target with CompilerTarget.Dll -> ".dll" | CompilerTarget.Module -> ".netmodule" | CompilerTarget.ConsoleExe | CompilerTarget.WinExe -> ".exe" - let implFiles = sourceFiles |> List.filter (fun lower -> List.exists (Filename.checkSuffix (String.lowercase lower)) FSharpImplFileSuffixes) + if Array.isEmpty sourceFiles then errorR (Error (FSComp.SR.buildNoInputsSpecified (), rangeCmdArgs)) + let outfile = - match tcConfigB.outputFile, List.rev implFiles with - | None, [] -> "out" + ext() - | None, h :: _ -> - let basic = fileNameOfPath h - let modname = try Filename.chopExtension basic with _ -> basic - modname+(ext()) - | Some f, _ -> f + match tcConfigB.outputFile with + | Some f -> f + | None -> + + let ext = + match tcConfigB.target with + | CompilerTarget.Dll -> ".dll" + | CompilerTarget.Module -> ".netmodule" + | CompilerTarget.ConsoleExe | CompilerTarget.WinExe -> ".exe" + + let lastImplFile = + sourceFiles |> Array.tryFindBack (fun lower -> + List.exists (checkSuffix (String.lowercase lower)) FSharpImplFileSuffixes) + + match lastImplFile with + | None -> "out" + ext + | Some last -> + let basic = fileNameOfPath last + let modname = try chopExtension basic with _ -> basic + modname + ext + let assemblyName = let baseName = fileNameOfPath outfile (fileNameWithoutExtension baseName) @@ -2514,8 +2527,8 @@ type TcConfigBuilder = | None -> // File doesn't exist in the paths. Assume it will be in the load-ed from directory. ComputeMakePathAbsolute pathLoadedFrom originalPath - if not (List.contains path (List.map (fun (_, _, path) -> path) tcConfigB.loadedSources)) then - tcConfigB.loadedSources <- tcConfigB.loadedSources ++ (m, originalPath, path) + if not (Array.exists (fun (_, _, sourcePath) -> sourcePath = path) tcConfigB.loadedSources) then + tcConfigB.loadedSources <- Array.append tcConfigB.loadedSources [| m, originalPath, path |] member tcConfigB.AddEmbeddedSourceFile (file) = tcConfigB.embedSourceList <- tcConfigB.embedSourceList ++ file @@ -2869,9 +2882,9 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member tcConfig.CloneOfOriginalBuilder = { data with conditionalCompilationDefines=data.conditionalCompilationDefines } - member tcConfig.ComputeCanContainEntryPoint(sourceFiles: string list) = - let n = sourceFiles.Length in - (sourceFiles |> List.mapi (fun i _ -> (i = n-1)), tcConfig.target.IsExe) + member tcConfig.ComputeCanContainEntryPoint(sourceFiles: string[]) = + let n = sourceFiles.Length in + (sourceFiles |> Array.mapi (fun i _ -> (i = n-1)), tcConfig.target.IsExe) // This call can fail if no CLR is found (this is the path to mscorlib) member tcConfig.GetTargetFrameworkDirectories() = @@ -2957,7 +2970,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = let lightOnByDefault = List.exists (Filename.checkSuffix lower) FSharpLightSyntaxFileSuffixes if lightOnByDefault then (tcConfig.light <> Some false) else (tcConfig.light = Some true ) - member tcConfig.GetAvailableLoadedSources() = + member tcConfig.GetAvailableLoadedSources(): (range * string)[] = use unwindBuildPhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parameter let resolveLoadedSource (m, originalPath, path) = try @@ -2977,8 +2990,8 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = with e -> errorRecovery e m; None tcConfig.loadedSources - |> List.choose resolveLoadedSource - |> List.distinct + |> Array.choose resolveLoadedSource + |> Array.distinct /// A closed set of assemblies where, for any subset S: /// - the TcImports object built for S (and thus the F# Compiler CCUs for the assemblies in S) @@ -3361,7 +3374,7 @@ let ComputeAnonModuleName check defaultNamespace filename (m: range) = mkRange filename pos0 pos0 pathToSynLid anonymousModuleNameRange (splitNamespace combined) -let PostParseModuleImpl (_i, defaultNamespace, isLastCompiland, filename, impl) = +let PostParseModuleImpl (_i, defaultNamespace, allowAnonModule, filename, impl) = match impl with | ParsedImplFileFragment.NamedModule(SynModuleOrNamespace(lid, isRec, kind, decls, xmlDoc, attribs, access, m)) -> let lid = @@ -3373,9 +3386,8 @@ let PostParseModuleImpl (_i, defaultNamespace, isLastCompiland, filename, impl) SynModuleOrNamespace(lid, isRec, kind, decls, xmlDoc, attribs, access, m) | ParsedImplFileFragment.AnonModule (defs, m)-> - let isLast, isExe = isLastCompiland let lower = String.lowercase filename - if not (isLast && isExe) && not (doNotRequireNamespaceOrModuleSuffixes |> List.exists (Filename.checkSuffix lower)) then + if not allowAnonModule && not (doNotRequireNamespaceOrModuleSuffixes |> List.exists (Filename.checkSuffix lower)) then match defs with | SynModuleDecl.NestedModule(_) :: _ -> errorR(Error(FSComp.SR.noEqualSignAfterModule(), trimRangeToLine m)) | _ -> errorR(Error(FSComp.SR.buildMultiFileRequiresNamespaceOrModule(), trimRangeToLine m)) @@ -3391,7 +3403,7 @@ let PostParseModuleImpl (_i, defaultNamespace, isLastCompiland, filename, impl) | _ -> lid, kind SynModuleOrNamespace(lid, a, kind, c, d, e, None, m) -let PostParseModuleSpec (_i, defaultNamespace, isLastCompiland, filename, intf) = +let PostParseModuleSpec (defaultNamespace, isLastCompiland, isExe, filename, intf) = match intf with | ParsedSigFileFragment.NamedModule(SynModuleOrNamespaceSig(lid, isRec, kind, decls, xmlDoc, attribs, access, m)) -> let lid = @@ -3403,9 +3415,8 @@ let PostParseModuleSpec (_i, defaultNamespace, isLastCompiland, filename, intf) SynModuleOrNamespaceSig(lid, isRec, NamedModule, decls, xmlDoc, attribs, access, m) | ParsedSigFileFragment.AnonModule (defs, m) -> - let isLast, isExe = isLastCompiland let lower = String.lowercase filename - if not (isLast && isExe) && not (doNotRequireNamespaceOrModuleSuffixes |> List.exists (Filename.checkSuffix lower)) then + if not (isLastCompiland && isExe) && not (doNotRequireNamespaceOrModuleSuffixes |> List.exists (Filename.checkSuffix lower)) then match defs with | SynModuleSigDecl.NestedModule(_) :: _ -> errorR(Error(FSComp.SR.noEqualSignAfterModule(), m)) | _ -> errorR(Error(FSComp.SR.buildMultiFileRequiresNamespaceOrModule(), m)) @@ -3423,13 +3434,15 @@ let PostParseModuleSpec (_i, defaultNamespace, isLastCompiland, filename, intf) -let PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, ParsedImplFile (hashDirectives, impls)) = +let PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, isExe, ParsedImplFile (hashDirectives, impls)) = match impls |> List.rev |> List.tryPick (function ParsedImplFileFragment.NamedModule(SynModuleOrNamespace(lid, _, _, _, _, _, _, _)) -> Some lid | _ -> None) with | Some lid when impls.Length > 1 -> errorR(Error(FSComp.SR.buildMultipleToplevelModules(), rangeOfLid lid)) | _ -> () - let impls = impls |> List.mapi (fun i x -> PostParseModuleImpl (i, defaultNamespace, isLastCompiland, filename, x)) + + let allowAnonModule = isLastCompiland && isExe + let impls = impls |> List.mapi (fun i x -> PostParseModuleImpl (i, defaultNamespace, allowAnonModule, filename, x)) let qualName = QualFileNameOfImpls filename impls let isScript = IsScript filename @@ -3443,14 +3456,14 @@ let PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, ParsedImp yield! GetScopedPragmasForHashDirective hd ] ParsedInput.ImplFile (ParsedImplFileInput (filename, isScript, qualName, scopedPragmas, hashDirectives, impls, isLastCompiland)) -let PostParseModuleSpecs (defaultNamespace, filename, isLastCompiland, ParsedSigFile (hashDirectives, specs)) = +let PostParseModuleSpecs (defaultNamespace, filename, isLastCompiland, isExe, ParsedSigFile (hashDirectives, specs)) = match specs |> List.rev |> List.tryPick (function ParsedSigFileFragment.NamedModule(SynModuleOrNamespaceSig(lid, _, _, _, _, _, _, _)) -> Some lid | _ -> None) with | Some lid when specs.Length > 1 -> errorR(Error(FSComp.SR.buildMultipleToplevelModules(), rangeOfLid lid)) | _ -> () - let specs = specs |> List.mapi (fun i x -> PostParseModuleSpec(i, defaultNamespace, isLastCompiland, filename, x)) + let specs = specs |> List.map (fun x -> PostParseModuleSpec(defaultNamespace, isLastCompiland, isExe, filename, x)) let qualName = QualFileNameOfSpecs filename specs let scopedPragmas = [ for (SynModuleOrNamespaceSig(_, _, _, decls, _, _, _, _)) in specs do @@ -3486,16 +3499,16 @@ let DeduplicateModuleName (moduleNamesDict: ModuleNamesDict) fileName (qualNameO /// Checks if a ParsedInput is using a module name that was already given and deduplicates the name if needed. let DeduplicateParsedInputModuleName (moduleNamesDict: ModuleNamesDict) input = match input with - | ParsedInput.ImplFile (ParsedImplFileInput.ParsedImplFileInput (fileName, isScript, qualNameOfFile, scopedPragmas, hashDirectives, modules, (isLastCompiland, isExe))) -> + | ParsedInput.ImplFile (ParsedImplFileInput.ParsedImplFileInput (fileName, isScript, qualNameOfFile, scopedPragmas, hashDirectives, modules, isLastCompiland)) -> let qualNameOfFileT, moduleNamesDictT = DeduplicateModuleName moduleNamesDict fileName qualNameOfFile - let inputT = ParsedInput.ImplFile (ParsedImplFileInput.ParsedImplFileInput (fileName, isScript, qualNameOfFileT, scopedPragmas, hashDirectives, modules, (isLastCompiland, isExe))) + let inputT = ParsedInput.ImplFile (ParsedImplFileInput.ParsedImplFileInput (fileName, isScript, qualNameOfFileT, scopedPragmas, hashDirectives, modules, isLastCompiland)) inputT, moduleNamesDictT | ParsedInput.SigFile (ParsedSigFileInput.ParsedSigFileInput (fileName, qualNameOfFile, scopedPragmas, hashDirectives, modules)) -> let qualNameOfFileT, moduleNamesDictT = DeduplicateModuleName moduleNamesDict fileName qualNameOfFile let inputT = ParsedInput.SigFile (ParsedSigFileInput.ParsedSigFileInput (fileName, qualNameOfFileT, scopedPragmas, hashDirectives, modules)) inputT, moduleNamesDictT -let ParseInput (lexer, errorLogger: ErrorLogger, lexbuf: UnicodeLexing.Lexbuf, defaultNamespace, filename, isLastCompiland) = +let ParseInput (lexer, errorLogger: ErrorLogger, lexbuf: UnicodeLexing.Lexbuf, defaultNamespace, filename, isLastCompiland, isExe) = // The assert below is almost ok, but it fires in two cases: // - fsi.exe sometimes passes "stdin" as a dummy filename // - if you have a #line directive, e.g. @@ -3516,10 +3529,10 @@ let ParseInput (lexer, errorLogger: ErrorLogger, lexbuf: UnicodeLexing.Lexbuf, d if FSharpImplFileSuffixes |> List.exists (Filename.checkSuffix lower) then let impl = Parser.implementationFile lexer lexbuf - PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, impl) + PostParseModuleImpls (defaultNamespace, filename, isLastCompiland, isExe, impl) elif FSharpSigFileSuffixes |> List.exists (Filename.checkSuffix lower) then let intfs = Parser.signatureFile lexer lexbuf - PostParseModuleSpecs (defaultNamespace, filename, isLastCompiland, intfs) + PostParseModuleSpecs (defaultNamespace, filename, isLastCompiland, isExe, intfs) else delayLogger.Error(Error(FSComp.SR.buildInvalidSourceFileExtension filename, Range.rangeStartup)) scopedPragmas <- GetScopedPragmasForInput input @@ -3533,7 +3546,7 @@ let ParseInput (lexer, errorLogger: ErrorLogger, lexbuf: UnicodeLexing.Lexbuf, d // parsing - ParseOneInputFile // Filename is (ml/mli/fs/fsi source). Parse it to AST. //---------------------------------------------------------------------------- -let ParseOneInputLexbuf (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, errorLogger) = +let ParseOneInputLexbuf (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, isExe, errorLogger) = use unwindbuildphase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse try let skip = true in (* don't report whitespace from lexer *) @@ -3560,7 +3573,7 @@ let ParseOneInputLexbuf (tcConfig: TcConfig, lexResourceManager, conditionalComp | IHash (_, m) -> dprintf "Parsed OK, got hash @ %a\n" outputRange m exit 0 - let res = ParseInput(tokenizer.Lexer, errorLogger, lexbuf, None, filename, isLastCompiland) + let res = ParseInput(tokenizer.Lexer, errorLogger, lexbuf, None, filename, isLastCompiland, isExe) if tcConfig.reportNumDecls then let rec flattenSpecs specs = @@ -3582,7 +3595,7 @@ let ParseOneInputLexbuf (tcConfig: TcConfig, lexResourceManager, conditionalComp with e -> (* errorR(Failure("parse failed")); *) errorRecovery e rangeStartup; None -let ParseOneInputFile (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, errorLogger, retryLocked) = +let ParseOneInputFile (tcConfig: TcConfig, lexResourceManager, conditionalCompilationDefines, filename, isLastCompiland, isExe, errorLogger, retryLocked) = try let lower = String.lowercase filename if List.exists (Filename.checkSuffix lower) (FSharpSigFileSuffixes@FSharpImplFileSuffixes) then @@ -3591,7 +3604,7 @@ let ParseOneInputFile (tcConfig: TcConfig, lexResourceManager, conditionalCompil let isFeatureSupported featureId = tcConfig.langVersion.SupportsFeature featureId use reader = File.OpenReaderAndRetry (filename, tcConfig.inputCodePage, retryLocked) let lexbuf = UnicodeLexing.StreamReaderAsLexbuf(isFeatureSupported, reader) - ParseOneInputLexbuf(tcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, errorLogger) + ParseOneInputLexbuf(tcConfig, lexResourceManager, conditionalCompilationDefines, lexbuf, filename, isLastCompiland, isExe, errorLogger) else error(Error(FSComp.SR.buildInvalidSourceFileExtension(SanitizeFileName filename tcConfig.implicitIncludeDir), rangeStartup)) with e -> (* errorR(Failure("parse failed")); *) errorRecovery e rangeStartup; None @@ -5149,9 +5162,9 @@ type LoadClosure = /// The list of references that were not resolved during load closure. These may still be extension references. UnresolvedReferences: UnresolvedAssemblyReference list /// The list of all sources in the closure with inputs when available - Inputs: LoadClosureInput list + Inputs: LoadClosureInput[] /// The #load, including those that didn't resolve - OriginalLoadReferences: (range * string * string) list + OriginalLoadReferences: (range * string * string)[] /// The #nowarns NoWarns: (string * range list) list /// Diagnostics seen while processing resolutions @@ -5205,8 +5218,9 @@ module ScriptPreprocessClosure = let isFeatureSupported featureId = tcConfig.langVersion.SupportsFeature featureId let lexbuf = UnicodeLexing.SourceTextAsLexbuf(isFeatureSupported, sourceText) - let isLastCompiland = (IsScript filename), tcConfig.target.IsExe // The root compiland is last in the list of compilands. - ParseOneInputLexbuf (tcConfig, lexResourceManager, defines, lexbuf, filename, isLastCompiland, errorLogger) + let isLastCompiland = IsScript filename // The root compiland is last in the list of compilands. + let isExe = tcConfig.target.IsExe + ParseOneInputLexbuf (tcConfig, lexResourceManager, defines, lexbuf, filename, isLastCompiland, isExe, errorLogger) /// Create a TcConfig for load closure starting from a single .fsx file let CreateScriptTextTcConfig @@ -5364,7 +5378,7 @@ module ScriptPreprocessClosure = yield! resolveDependencyManagerSources filename let postSources = tcConfig.GetAvailableLoadedSources() - let sources = if preSources.Length < postSources.Length then postSources.[preSources.Length..] else [] + let sources = if preSources.Length < postSources.Length then postSources.[preSources.Length..] else Array.Empty() yield! resolveDependencyManagerSources filename for (m, subFile) in sources do @@ -5399,10 +5413,9 @@ module ScriptPreprocessClosure = Some(ParsedInput.ImplFile (ParsedImplFileInput (name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags, _))), parseDiagnostics, metaDiagnostics, nowarns) -> - let isLastCompiland = (true, tcConfig.target.IsExe) rest @ [ClosureFile (filename, m, - Some(ParsedInput.ImplFile (ParsedImplFileInput (name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags, isLastCompiland))), + Some(ParsedInput.ImplFile (ParsedImplFileInput (name, isScript, qualNameOfFile, scopedPragmas, hashDirectives, implFileFlags, true))), parseDiagnostics, metaDiagnostics, nowarns)] | _ -> closureFiles @@ -5411,11 +5424,11 @@ module ScriptPreprocessClosure = let sourceFiles = [ for (ClosureFile(filename, m, _, _, _, _)) in closureFiles -> (filename, m) ] let sourceInputs = - [ for (ClosureFile(filename, _, input, parseDiagnostics, metaDiagnostics, _nowarns)) in closureFiles -> + [| for (ClosureFile(filename, _, input, parseDiagnostics, metaDiagnostics, _nowarns)) in closureFiles -> ({ FileName=filename SyntaxTree=input ParseDiagnostics=parseDiagnostics - MetaCommandDiagnostics=metaDiagnostics } : LoadClosureInput) ] + MetaCommandDiagnostics=metaDiagnostics } : LoadClosureInput) |] let globalNoWarns = closureFiles |> List.collect (fun (ClosureFile(_, _, _, _, _, noWarns)) -> noWarns) @@ -5787,23 +5800,23 @@ let TypeCheckOneInput (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, pre /// Finish checking multiple files (or one interactive entry into F# Interactive) let TypeCheckMultipleInputsFinish(results, tcState: TcState) = - let tcEnvsAtEndFile, topAttrs, implFiles, ccuSigsForFiles = List.unzip4 results - let topAttrs = List.foldBack CombineTopAttrs topAttrs EmptyTopAttrs - let implFiles = List.choose id implFiles + let tcEnvsAtEndFile, topAttrs, implFiles, ccuSigsForFiles = Array.unzip4 results + let topAttrs = Array.foldBack CombineTopAttrs topAttrs EmptyTopAttrs + let implFiles = Array.choose id implFiles // This is the environment required by fsi.exe when incrementally adding definitions - let tcEnvAtEndOfLastFile = (match tcEnvsAtEndFile with h :: _ -> h | _ -> tcState.TcEnvFromSignatures) + let tcEnvAtEndOfLastFile = if Array.isEmpty tcEnvsAtEndFile then tcState.TcEnvFromSignatures else tcEnvsAtEndFile.[0] (tcEnvAtEndOfLastFile, topAttrs, implFiles, ccuSigsForFiles), tcState let TypeCheckOneInputAndFinishEventually(checkForErrors, tcConfig: TcConfig, tcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input) = eventually { Logger.LogBlockStart LogCompilerFunctionId.CompileOps_TypeCheckOneInputAndFinishEventually let! results, tcState = TypeCheckOneInputEventually(checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input) - let result = TypeCheckMultipleInputsFinish([results], tcState) + let result = TypeCheckMultipleInputsFinish([|results|], tcState) Logger.LogBlockStop LogCompilerFunctionId.CompileOps_TypeCheckOneInputAndFinishEventually return result } -let TypeCheckClosedInputSetFinish (declaredImpls: TypedImplFile list, tcState) = +let TypeCheckClosedInputSetFinish (declaredImpls: TypedImplFile[], tcState) = // Publish the latest contents to the CCU tcState.tcsCcu.Deref.Contents <- Construct.NewCcuContents ILScopeRef.Local range0 tcState.tcsCcu.AssemblyName tcState.tcsCcuSig @@ -5816,7 +5829,7 @@ let TypeCheckClosedInputSetFinish (declaredImpls: TypedImplFile list, tcState) = let TypeCheckClosedInputSet (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcState, inputs) = // tcEnvAtEndOfLastFile is the environment required by fsi.exe when incrementally adding definitions - let results, tcState = (tcState, inputs) ||> List.mapFold (TypeCheckOneInput (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt)) + let results, tcState = (tcState, inputs) ||> Array.mapFold (TypeCheckOneInput (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt)) let (tcEnvAtEndOfLastFile, topAttrs, implFiles, _), tcState = TypeCheckMultipleInputsFinish(results, tcState) let tcState, declaredImpls = TypeCheckClosedInputSetFinish (implFiles, tcState) tcState, topAttrs, declaredImpls, tcEnvAtEndOfLastFile diff --git a/src/fsharp/CompileOps.fsi b/src/fsharp/CompileOps.fsi index 31407c3b956..8f135908a35 100644 --- a/src/fsharp/CompileOps.fsi +++ b/src/fsharp/CompileOps.fsi @@ -77,7 +77,7 @@ type ModuleNamesDict = Map> val DeduplicateParsedInputModuleName: ModuleNamesDict -> ParsedInput -> ParsedInput * ModuleNamesDict /// Parse a single input (A signature file or implementation file) -val ParseInput: (UnicodeLexing.Lexbuf -> Parser.token) * ErrorLogger * UnicodeLexing.Lexbuf * string option * string * isLastCompiland:(bool * bool) -> ParsedInput +val ParseInput: (UnicodeLexing.Lexbuf -> Parser.token) * ErrorLogger * UnicodeLexing.Lexbuf * string option * string * isLastCompiland: bool * isExe: bool -> ParsedInput //---------------------------------------------------------------------------- // Error and warnings @@ -274,7 +274,7 @@ type TcConfigBuilder = mutable light: bool option mutable conditionalCompilationDefines: string list /// Sources added into the build with #load - mutable loadedSources: (range * string * string) list + mutable loadedSources: (range * string * string)[] mutable compilerToolPaths: string list mutable referencedDLLs: AssemblyReference list mutable packageManagerLines: Map @@ -413,7 +413,7 @@ type TcConfigBuilder = tryGetMetadataSnapshot: ILReaderTryGetMetadataSnapshot -> TcConfigBuilder - member DecideNames: string list -> outfile: string * pdbfile: string option * assemblyName: string + member DecideNames: string[] -> outfile: string * pdbfile: string option * assemblyName: string member TurnWarningOff: range * string -> unit member TurnWarningOn: range * string -> unit member AddIncludePath: range * string * string -> unit @@ -547,9 +547,9 @@ type TcConfig = member GetTargetFrameworkDirectories: unit -> string list /// Get the loaded sources that exist and issue a warning for the ones that don't - member GetAvailableLoadedSources: unit -> (range*string) list + member GetAvailableLoadedSources: unit -> (range * string)[] - member ComputeCanContainEntryPoint: sourceFiles:string list -> bool list *bool + member ComputeCanContainEntryPoint: sourceFiles: string[] -> bool[] * bool /// File system query based on TcConfig settings member ResolveSourceFile: range * filename: string * pathLoadedFrom: string -> string @@ -722,7 +722,7 @@ val DefaultReferencesForScriptsAndOutOfProjectSources: bool -> string list //-------------------------------------------------------------------------- /// Parse one input file -val ParseOneInputFile: TcConfig * Lexhelp.LexResourceManager * string list * string * isLastCompiland: (bool * bool) * ErrorLogger * (*retryLocked*) bool -> ParsedInput option +val ParseOneInputFile: TcConfig * Lexhelp.LexResourceManager * string list * string * isLastCompiland: bool * isExe: bool * ErrorLogger * (*retryLocked*) bool -> ParsedInput option //---------------------------------------------------------------------------- // Type checking and querying the type checking state @@ -764,18 +764,18 @@ val TypeCheckOneInputEventually : -> Eventually<(TcEnv * TopAttribs * TypedImplFile option * ModuleOrNamespaceType) * TcState> /// Finish the checking of multiple inputs -val TypeCheckMultipleInputsFinish: (TcEnv * TopAttribs * 'T option * 'U) list * TcState -> (TcEnv * TopAttribs * 'T list * 'U list) * TcState +val TypeCheckMultipleInputsFinish: (TcEnv * TopAttribs * 'T option * 'U)[] * TcState -> (TcEnv * TopAttribs * 'T[] * 'U[]) * TcState /// Finish the checking of a closed set of inputs -val TypeCheckClosedInputSetFinish: TypedImplFile list * TcState -> TcState * TypedImplFile list +val TypeCheckClosedInputSetFinish: TypedImplFile[] * TcState -> TcState * TypedImplFile[] /// Check a closed set of inputs -val TypeCheckClosedInputSet: CompilationThreadToken * checkForErrors: (unit -> bool) * TcConfig * TcImports * TcGlobals * LongIdent option * TcState * ParsedInput list -> TcState * TopAttribs * TypedImplFile list * TcEnv +val TypeCheckClosedInputSet: CompilationThreadToken * checkForErrors: (unit -> bool) * TcConfig * TcImports * TcGlobals * LongIdent option * TcState * ParsedInput[] -> TcState * TopAttribs * TypedImplFile[] * TcEnv /// Check a single input and finish the checking val TypeCheckOneInputAndFinishEventually : checkForErrors: (unit -> bool) * TcConfig * TcImports * TcGlobals * LongIdent option * NameResolution.TcResultsSink * TcState * ParsedInput - -> Eventually<(TcEnv * TopAttribs * TypedImplFile list * ModuleOrNamespaceType list) * TcState> + -> Eventually<(TcEnv * TopAttribs * TypedImplFile[] * ModuleOrNamespaceType[]) * TcState> /// Indicates if we should report a warning val ReportWarning: FSharpErrorSeverityOptions -> PhasedDiagnostic -> bool @@ -812,10 +812,10 @@ type LoadClosure = UnresolvedReferences: UnresolvedAssemblyReference list /// The list of all sources in the closure with inputs when available, with associated parse errors and warnings - Inputs: LoadClosureInput list + Inputs: LoadClosureInput[] /// The original #load references, including those that didn't resolve - OriginalLoadReferences: (range * string * string) list + OriginalLoadReferences: (range * string * string)[] /// The #nowarns NoWarns: (string * range list) list diff --git a/src/fsharp/CompileOptions.fs b/src/fsharp/CompileOptions.fs index 4b5ff777e62..08675bf433e 100644 --- a/src/fsharp/CompileOptions.fs +++ b/src/fsharp/CompileOptions.fs @@ -1584,12 +1584,12 @@ let GetCoreFsiCompilerOptions (tcConfigB: TcConfigBuilder) = testingAndQAFlags tcConfigB]) ] -let ApplyCommandLineArgs(tcConfigB: TcConfigBuilder, sourceFiles: string list, commandLineArgs) = +let ApplyCommandLineArgs(tcConfigB: TcConfigBuilder, sourceFiles: string[], commandLineArgs) = try let sourceFilesAcc = ResizeArray sourceFiles let collect name = if not (Filename.isDll name) then sourceFilesAcc.Add name ParseCompilerOptions(collect, GetCoreServiceCompilerOptions tcConfigB, commandLineArgs) - ResizeArray.toList sourceFilesAcc + ResizeArray.toArray sourceFilesAcc with e -> errorRecovery e range0 sourceFiles @@ -1695,16 +1695,17 @@ let GetInitialOptimizationEnv (tcImports:TcImports, tcGlobals:TcGlobals) = let optEnv = List.fold (AddExternalCcuToOptimizationEnv tcGlobals) optEnv ccuinfos optEnv -let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importMap, isIncrementalFragment, optEnv, ccu:CcuThunk, implFiles) = +let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importMap, isIncrementalFragment, optEnv, ccu:CcuThunk, implFiles: _[]) = // NOTE: optEnv - threads through // // Always optimize once - the results of this step give the x-module optimization // info. Subsequent optimization steps choose representations etc. which we don't // want to save in the x-module info (i.e. x-module info is currently "high level"). - PrintWholeAssemblyImplementation tcGlobals tcConfig outfile "pass-start" implFiles + let implFilesArray = List.ofArray implFiles + PrintWholeAssemblyImplementation tcGlobals tcConfig outfile "pass-start" implFilesArray #if DEBUG if tcConfig.showOptimizationData then - dprintf "Expression prior to optimization:\n%s\n" (Layout.showL (Layout.squashTo 192 (DebugPrint.implFilesL tcGlobals implFiles))) + dprintf "Expression prior to optimization:\n%s\n" (Layout.showL (Layout.squashTo 192 (DebugPrint.implFilesL tcGlobals implFilesArray))) if tcConfig.showOptimizationData then dprintf "CCU prior to optimization:\n%s\n" (Layout.showL (Layout.squashTo 192 (DebugPrint.entityL tcGlobals ccu.Contents))) @@ -1721,7 +1722,7 @@ let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importM let results, (optEnvFirstLoop, _, _, _) = ((optEnv0, optEnv0, optEnv0, SignatureHidingInfo.Empty), implFiles) - ||> List.mapFold (fun (optEnvFirstLoop, optEnvExtraLoop, optEnvFinalSimplify, hidden) implFile -> + ||> Array.mapFold (fun (optEnvFirstLoop, optEnvExtraLoop, optEnvFinalSimplify, hidden) implFile -> //ReportTime tcConfig ("Initial simplify") let (optEnvFirstLoop, implFile, implFileOptData, hidden), optimizeDuringCodeGen = @@ -1786,10 +1787,10 @@ let ApplyAllOptimizations (tcConfig:TcConfig, tcGlobals, tcVal, outfile, importM ((implFile, optimizeDuringCodeGen), implFileOptData), (optEnvFirstLoop, optEnvExtraLoop, optEnvFinalSimplify, hidden)) - let implFiles, implFileOptDatas = List.unzip results + let implFiles, implFileOptDatas = Array.unzip results let assemblyOptData = Optimizer.UnionOptimizationInfos implFileOptDatas let tassembly = TypedAssemblyAfterOptimization implFiles - PrintWholeAssemblyImplementation tcGlobals tcConfig outfile "pass-end" (List.map fst implFiles) + PrintWholeAssemblyImplementation tcGlobals tcConfig outfile "pass-end" (Array.map fst implFiles |> List.ofArray) ReportTime tcConfig ("Ending Optimizations") tassembly, assemblyOptData, optEnvFirstLoop diff --git a/src/fsharp/CompileOptions.fsi b/src/fsharp/CompileOptions.fsi index df759ecdcc7..c3390c5cb3d 100644 --- a/src/fsharp/CompileOptions.fsi +++ b/src/fsharp/CompileOptions.fsi @@ -66,7 +66,7 @@ val GetCoreFsiCompilerOptions : TcConfigBuilder -> CompilerOptionBlock list val GetCoreServiceCompilerOptions : TcConfigBuilder -> CompilerOptionBlock list /// Apply args to TcConfigBuilder and return new list of source files -val ApplyCommandLineArgs: tcConfigB: TcConfigBuilder * sourceFiles: string list * argv: string list -> string list +val ApplyCommandLineArgs: tcConfigB: TcConfigBuilder * sourceFiles: string[] * argv: string list -> string[] // Expose the "setters" for some user switches, to enable setting of defaults val SetOptimizeSwitch : TcConfigBuilder -> OptionSwitch -> unit @@ -79,7 +79,7 @@ val GetGeneratedILModuleName : CompilerTarget -> string -> string val GetInitialOptimizationEnv : TcImports * TcGlobals -> IncrementalOptimizationEnv val AddExternalCcuToOptimizationEnv : TcGlobals -> IncrementalOptimizationEnv -> ImportedAssembly -> IncrementalOptimizationEnv -val ApplyAllOptimizations : TcConfig * TcGlobals * ConstraintSolver.TcValF * string * ImportMap * bool * IncrementalOptimizationEnv * CcuThunk * TypedImplFile list -> TypedAssemblyAfterOptimization * Optimizer.LazyModuleInfo * IncrementalOptimizationEnv +val ApplyAllOptimizations : TcConfig * TcGlobals * ConstraintSolver.TcValF * string * ImportMap * bool * IncrementalOptimizationEnv * CcuThunk * TypedImplFile[] -> TypedAssemblyAfterOptimization * Optimizer.LazyModuleInfo * IncrementalOptimizationEnv val CreateIlxAssemblyGenerator : TcConfig * TcImports * TcGlobals * ConstraintSolver.TcValF * CcuThunk -> IlxGen.IlxAssemblyGenerator diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index ef6093be8ce..934a8f9c673 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -1237,7 +1237,7 @@ and AddBindingsForModuleTopVals _g allocVal _cloc eenv vs = let AddIncrementalLocalAssemblyFragmentToIlxGenEnv (amap: ImportMap, isIncrementalFragment, g, ccu, fragName, intraAssemblyInfo, eenv, typedImplFiles) = let cloc = CompLocForFragment fragName ccu let allocVal = ComputeAndAddStorageForLocalTopVal (amap, g, intraAssemblyInfo, true, NoShadowLocal) - (eenv, typedImplFiles) ||> List.fold (fun eenv (TImplFile (qname, _, mexpr, _, _, _)) -> + (eenv, typedImplFiles) ||> Array.fold (fun eenv (TImplFile (qname, _, mexpr, _, _, _)) -> let cloc = { cloc with TopImplQualifiedName = qname.Text } if isIncrementalFragment then match mexpr with @@ -7610,9 +7610,9 @@ and GenExnDef cenv mgbuf eenv m (exnc: Tycon) = let CodegenAssembly cenv eenv mgbuf fileImpls = - if not (isNil fileImpls) then - let a, b = List.frontAndBack fileImpls - let eenv = List.fold (GenTopImpl cenv mgbuf None) eenv a + if not (Array.isEmpty fileImpls) then + let a, b = Array.take (fileImpls.Length - 1) fileImpls, Array.last fileImpls + let eenv = Array.fold (GenTopImpl cenv mgbuf None) eenv a let eenv = GenTopImpl cenv mgbuf cenv.opts.mainMethodInfo eenv b // Some constructs generate residue types and bindings. Generate these now. They don't result in any diff --git a/src/fsharp/IlxGen.fsi b/src/fsharp/IlxGen.fsi index 8bd6bf7e348..8bebcdd0295 100644 --- a/src/fsharp/IlxGen.fsi +++ b/src/fsharp/IlxGen.fsi @@ -96,7 +96,7 @@ type public IlxAssemblyGenerator = /// Register a fragment of the current assembly with the ILX code generator. If 'isIncrementalFragment' is true then the input /// is assumed to be a fragment 'typed' into FSI.EXE, otherwise the input is assumed to be the result of a '#load' - member AddIncrementalLocalAssemblyFragment: isIncrementalFragment: bool * fragName:string * typedImplFiles: TypedImplFile list -> unit + member AddIncrementalLocalAssemblyFragment: isIncrementalFragment: bool * fragName:string * typedImplFiles: TypedImplFile[] -> unit /// Generate ILX code for an assembly fragment member GenerateCode: IlxGenOptions * TypedAssemblyAfterOptimization * Attribs * Attribs -> IlxGenResults diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index b03db035cf9..71f48f9c7cb 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -209,7 +209,7 @@ type cenv = reportErrors: bool - isLastCompiland : bool*bool + isLastCompiland: bool isInternalTestSpanStackReferring: bool @@ -1790,8 +1790,7 @@ let CheckModuleBinding cenv env (TBind(v, e, _) as bind) = let isExplicitEntryPoint = HasFSharpAttribute g g.attrib_EntryPointAttribute v.Attribs if isExplicitEntryPoint then cenv.entryPointGiven <- true - let isLastCompiland = fst cenv.isLastCompiland - if not isLastCompiland && cenv.reportErrors then + if not cenv.isLastCompiland && cenv.reportErrors then errorR(Error(FSComp.SR.chkEntryPointUsage(), v.Range)) // Analyze the r.h.s. for the "IsCompiledAsStaticPropertyWithoutField" condition @@ -2293,7 +2292,7 @@ and CheckModuleSpec cenv env x = let env = { env with reflect = env.reflect || HasFSharpAttribute cenv.g cenv.g.attrib_ReflectedDefinitionAttribute mspec.Attribs } CheckDefnInModule cenv env rhs -let CheckTopImpl (g, amap, reportErrors, infoReader, internalsVisibleToPaths, viewCcu, denv, mexpr, extraAttribs, (isLastCompiland: bool*bool), isInternalTestSpanStackReferring) = +let CheckTopImpl (g, amap, reportErrors, infoReader, internalsVisibleToPaths, viewCcu, denv, mexpr, extraAttribs, (isLastCompiland: bool), isInternalTestSpanStackReferring) = let cenv = { g =g reportErrors=reportErrors diff --git a/src/fsharp/PostInferenceChecks.fsi b/src/fsharp/PostInferenceChecks.fsi index 312da640278..782376782e9 100644 --- a/src/fsharp/PostInferenceChecks.fsi +++ b/src/fsharp/PostInferenceChecks.fsi @@ -20,6 +20,7 @@ val CheckTopImpl: viewCcu: CcuThunk * denv: DisplayEnv * mexpr: ModuleOrNamespaceExprWithSig * - extraAttribs: Attribs * (bool * bool) * + extraAttribs: Attribs * + isLastCompiland: bool * isInternalTestSpanStackReferring: bool -> bool * StampMap diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index d3a185d8635..de7834dbddd 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -2241,7 +2241,7 @@ type ParsedImplFileInput = scopedPragmas: ScopedPragma list * hashDirectives: ParsedHashDirective list * modules: SynModuleOrNamespace list * - isLastCompiland: (bool * bool) + isLastCompiland: bool /// Represents the full syntax tree, file name and other parsing information for a signature file [] diff --git a/src/fsharp/TypedTree.fs b/src/fsharp/TypedTree.fs index 8b12eb84295..000e30ed427 100644 --- a/src/fsharp/TypedTree.fs +++ b/src/fsharp/TypedTree.fs @@ -4933,7 +4933,7 @@ type TypedImplFile = /// Represents a complete typechecked assembly, made up of multiple implementation files. [] type TypedAssemblyAfterOptimization = - | TypedAssemblyAfterOptimization of (TypedImplFile * (* optimizeDuringCodeGen: *) (Expr -> Expr)) list + | TypedAssemblyAfterOptimization of (TypedImplFile * (* optimizeDuringCodeGen: *) (Expr -> Expr))[] [] member x.DebugText = x.ToString() diff --git a/src/fsharp/fsc.fs b/src/fsharp/fsc.fs index 3ef65d7a865..b5a092221ea 100644 --- a/src/fsharp/fsc.fs +++ b/src/fsharp/fsc.fs @@ -189,9 +189,9 @@ type DisposablesTracker() = try i.Dispose() with _ -> () -let TypeCheck (ctok, tcConfig, tcImports, tcGlobals, errorLogger: ErrorLogger, assemblyName, niceNameGen, tcEnv0, inputs, exiter: Exiter) = +let TypeCheck (ctok, tcConfig, tcImports, tcGlobals, errorLogger: ErrorLogger, assemblyName, niceNameGen, tcEnv0, inputs: _[], exiter: Exiter) = try - if isNil inputs then error(Error(FSComp.SR.fscNoImplementationFiles(), Range.rangeStartup)) + if Array.isEmpty inputs then error(Error(FSComp.SR.fscNoImplementationFiles(), Range.rangeStartup)) let ccuName = assemblyName let tcInitialState = GetInitialTcState (rangeStartup, ccuName, tcConfig, tcGlobals, tcImports, niceNameGen, tcEnv0) TypeCheckClosedInputSet (ctok, (fun () -> errorLogger.ErrorCount > 0), tcConfig, tcImports, tcGlobals, None, tcInitialState, inputs) @@ -200,7 +200,7 @@ let TypeCheck (ctok, tcConfig, tcImports, tcGlobals, errorLogger: ErrorLogger, a exiter.Exit 1 /// Check for .fsx and, if present, compute the load closure for of #loaded files. -let AdjustForScriptCompile(ctok, tcConfigB: TcConfigBuilder, commandLineSourceFiles, lexResourceManager) = +let AdjustForScriptCompile(ctok, tcConfigB: TcConfigBuilder, commandLineSourceFiles, lexResourceManager): string[] = let combineFilePath file = try @@ -244,7 +244,7 @@ let AdjustForScriptCompile(ctok, tcConfigB: TcConfigBuilder, commandLineSourceFi // Find closure of .fsx files. commandLineSourceFiles |> List.iter AppendClosureInformation - List.rev allSources + allSources |> Array.ofList |> Array.rev let ProcessCommandLineFlags (tcConfigB: TcConfigBuilder, setProcessThreadLocals, lcidFromCodePage, argv) = let mutable inputFilesRef = [] @@ -1772,7 +1772,7 @@ let main0(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, let lexResourceManager = new Lexhelp.LexResourceManager() // process command line, flags and collect filenames - let sourceFiles = + let sourceFiles: string[] = // The ParseCompilerOptions function calls imperative function to process "real" args // Rather than start processing, just collect names, then process them. @@ -1839,12 +1839,12 @@ let main0(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, use unwindParsePhase = PushThreadBuildPhaseUntilUnwind BuildPhase.Parse let inputs = try - let isLastCompiland, isExe = sourceFiles |> tcConfig.ComputeCanContainEntryPoint - isLastCompiland |> List.zip sourceFiles + let isLastCompiland, isExe = tcConfig.ComputeCanContainEntryPoint sourceFiles + Array.zip sourceFiles isLastCompiland // PERF: consider making this parallel, once uses of global state relevant to parsing are cleaned up - |> List.choose (fun (filename: string, isLastCompiland) -> + |> Array.choose (fun (filename: string, isLastCompiland) -> let pathOfMetaCommandSource = Path.GetDirectoryName filename - match ParseOneInputFile(tcConfig, lexResourceManager, ["COMPILED"], filename, (isLastCompiland, isExe), errorLogger, (*retryLocked*)false) with + match ParseOneInputFile(tcConfig, lexResourceManager, ["COMPILED"], filename, isLastCompiland, isExe, errorLogger, (*retryLocked*)false) with | Some input -> Some (input, pathOfMetaCommandSource) | None -> None ) @@ -1854,16 +1854,16 @@ let main0(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, let inputs, _ = (Map.empty, inputs) - ||> List.mapFold (fun state (input,x) -> let inputT, stateT = DeduplicateParsedInputModuleName state input in (inputT,x), stateT) + ||> Array.mapFold (fun state (input,x) -> let inputT, stateT = DeduplicateParsedInputModuleName state input in (inputT,x), stateT) if tcConfig.parseOnly then exiter.Exit 0 if not tcConfig.continueAfterParseFailure then AbortOnError(errorLogger, exiter) if tcConfig.printAst then - inputs |> List.iter (fun (input, _filename) -> printf "AST:\n"; printfn "%+A" input; printf "\n") + inputs |> Array.iter (fun (input, _filename) -> printf "AST:\n"; printfn "%+A" input; printf "\n") - let tcConfig = (tcConfig, inputs) ||> List.fold (fun z (x, m) -> ApplyMetaCommandsFromInputToTcConfig(z, x, m)) + let tcConfig = (tcConfig, inputs) ||> Array.fold (fun z (x, m) -> ApplyMetaCommandsFromInputToTcConfig(z, x, m)) let tcConfigP = TcConfigProvider.Constant tcConfig // Import other assemblies @@ -1884,7 +1884,7 @@ let main0(ctok, argv, legacyReferenceResolver, bannerAlreadyPrinted, let tcEnv0 = GetInitialTcEnv (assemblyName, rangeStartup, tcConfig, tcImports, tcGlobals) // Type check the inputs - let inputs = inputs |> List.map fst + let inputs = Array.map fst inputs let tcState, topAttrs, typedAssembly, _tcEnvAtEnd = TypeCheck(ctok, tcConfig, tcImports, tcGlobals, errorLogger, assemblyName, NiceNameGenerator(), tcEnv0, inputs, exiter) @@ -1946,7 +1946,7 @@ let main1(Args (ctok, tcGlobals, tcImports: TcImports, frameworkTcImports, gener // This is for the compile-from-AST feature of FCS. // TODO: consider removing this feature from FCS, which as far as I know is not used by anyone. -let main1OfAst (ctok, legacyReferenceResolver, reduceMemoryUsage, assemblyName, target, outfile, pdbFile, dllReferences, noframework, exiter, errorLoggerProvider: ErrorLoggerProvider, inputs : ParsedInput list) = +let main1OfAst (ctok, legacyReferenceResolver, reduceMemoryUsage, assemblyName, target, outfile, pdbFile, dllReferences, noframework, exiter, errorLoggerProvider: ErrorLoggerProvider, inputs: ParsedInput[]) = let tryGetMetadataSnapshot = (fun _ -> None) @@ -1988,7 +1988,7 @@ let main1OfAst (ctok, legacyReferenceResolver, reduceMemoryUsage, assemblyName, use unwindParsePhase = PushThreadBuildPhaseUntilUnwind (BuildPhase.Parse) let meta = Directory.GetCurrentDirectory() - let tcConfig = (tcConfig,inputs) ||> List.fold (fun tcc inp -> ApplyMetaCommandsFromInputToTcConfig (tcc, inp,meta)) + let tcConfig = (tcConfig,inputs) ||> Array.fold (fun tcc inp -> ApplyMetaCommandsFromInputToTcConfig (tcc, inp,meta)) let tcConfigP = TcConfigProvider.Constant tcConfig let tcGlobals,tcImports = @@ -2026,7 +2026,7 @@ let main1OfAst (ctok, legacyReferenceResolver, reduceMemoryUsage, assemblyName, /// Phase 2a: encode signature data, optimize, encode optimization data let main2a(Args (ctok, tcConfig, tcImports, frameworkTcImports: TcImports, tcGlobals, - errorLogger: ErrorLogger, generatedCcu: CcuThunk, outfile, typedImplFiles, + errorLogger: ErrorLogger, generatedCcu: CcuThunk, outfile, typedImplFiles: _[], topAttrs, pdbfile, assemblyName, assemVerFromAttrib, signingInfo, exiter: Exiter)) = // Encode the signature data diff --git a/src/fsharp/fsc.fsi b/src/fsharp/fsc.fsi index ae90b34b822..f3645800d00 100755 --- a/src/fsharp/fsc.fsi +++ b/src/fsharp/fsc.fsi @@ -71,7 +71,7 @@ val compileOfAst : noframework:bool * exiter:Exiter * loggerProvider: ErrorLoggerProvider * - inputs:ParsedInput list * + inputs:ParsedInput[] * tcImportsCapture : (TcImports -> unit) option * dynamicAssemblyCreator: (TcGlobals * string * ILModuleDef -> unit) option -> unit diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 35d8e32dc4f..7d8def7878c 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -1205,7 +1205,7 @@ type internal FsiDynamicCompiler errorLogger.AbortOnError(fsiConsoleOutput); codegenResults, optEnv, fragName - let ProcessInputs (ctok, errorLogger: ErrorLogger, istate: FsiDynamicCompilerState, inputs: ParsedInput list, showTypes: bool, isIncrementalFragment: bool, isInteractiveItExpr: bool, prefixPath: LongIdent) = + let ProcessInputs (ctok, errorLogger: ErrorLogger, istate: FsiDynamicCompilerState, inputs: ParsedInput[], showTypes: bool, isIncrementalFragment: bool, isInteractiveItExpr: bool, prefixPath: LongIdent) = let optEnv = istate.optEnv let tcState = istate.tcState let ilxGenerator = istate.ilxGenerator @@ -1293,7 +1293,7 @@ type internal FsiDynamicCompiler let i = nextFragmentId() let prefix = mkFragmentPath i // Ensure the path includes the qualifying name - let inputs = inputs |> List.map (PrependPathToInput prefix) + let inputs = inputs |> Array.map (PrependPathToInput prefix) let istate,_,_ = ProcessInputs (ctok, errorLogger, istate, inputs, true, false, false, prefix) istate @@ -1304,8 +1304,8 @@ type internal FsiDynamicCompiler let prefix = mkFragmentPath i let prefixPath = pathOfLid prefix let impl = SynModuleOrNamespace(prefix,(*isRec*)false, NamedModule,defs,PreXmlDoc.Empty,[],None,rangeStdin) - let input = ParsedInput.ImplFile (ParsedImplFileInput (filename,true, ComputeQualifiedNameOfFileFromUniquePath (rangeStdin,prefixPath),[],[],[impl],(true (* isLastCompiland *), false (* isExe *)) )) - let istate,tcEnvAtEndOfLastInput,declaredImpls = ProcessInputs (ctok, errorLogger, istate, [input], showTypes, true, isInteractiveItExpr, prefix) + let input = ParsedInput.ImplFile (ParsedImplFileInput (filename,true, ComputeQualifiedNameOfFileFromUniquePath (rangeStdin,prefixPath),[],[],[impl], true)) + let istate,tcEnvAtEndOfLastInput,declaredImpls = ProcessInputs (ctok, errorLogger, istate, [|input|], showTypes, true, isInteractiveItExpr, prefix) let tcState = istate.tcState let newState = { istate with tcState = tcState.NextStateAfterIncrementalFragment(tcEnvAtEndOfLastInput) } processContents newState declaredImpls @@ -1470,7 +1470,7 @@ type internal FsiDynamicCompiler // Intent "[Loading %s]\n" (String.concat "\n and " sourceFiles) fsiConsoleOutput.uprintf "[%s " (FSIstrings.SR.fsiLoadingFilesPrefixText()) - closure.Inputs |> List.iteri (fun i input -> + closure.Inputs |> Array.iteri (fun i input -> if i=0 then fsiConsoleOutput.uprintf "%s" input.FileName else fsiConsoleOutput.uprintnf " %s %s" (FSIstrings.SR.fsiLoadingFilesPrefixText()) input.FileName) fsiConsoleOutput.uprintfn "]" @@ -1483,20 +1483,20 @@ type internal FsiDynamicCompiler // Non-scripts will not have been parsed during #load closure so parse them now let sourceFiles,inputs = closure.Inputs - |> List.map (fun input-> + |> Array.map (fun input-> input.ParseDiagnostics |> List.iter diagnosticSink input.MetaCommandDiagnostics |> List.iter diagnosticSink let parsedInput = match input.SyntaxTree with - | None -> ParseOneInputFile(tcConfig,lexResourceManager,["INTERACTIVE"],input.FileName,(true,false),errorLogger,(*retryLocked*)false) + | None -> ParseOneInputFile(tcConfig,lexResourceManager,["INTERACTIVE"],input.FileName,true,false,errorLogger,(*retryLocked*)false) | _-> input.SyntaxTree input.FileName, parsedInput) - |> List.unzip + |> Array.unzip errorLogger.AbortOnError(fsiConsoleOutput); - if inputs |> List.exists Option.isNone then failwith "parse error" - let inputs = List.map Option.get inputs - let istate = (istate, sourceFiles, inputs) |||> List.fold2 (fun istate sourceFile input -> fsiDynamicCompiler.ProcessMetaCommandsFromInputAsInteractiveCommands(ctok, istate, sourceFile, input)) + if inputs |> Array.exists Option.isNone then failwith "parse error" + let inputs = Array.map Option.get inputs + let istate = (istate, sourceFiles, inputs) |||> Array.fold2 (fun istate sourceFile input -> fsiDynamicCompiler.ProcessMetaCommandsFromInputAsInteractiveCommands(ctok, istate, sourceFile, input)) fsiDynamicCompiler.EvalParsedSourceFiles (ctok, errorLogger, istate, inputs) member __.GetBoundValues istate = @@ -1593,7 +1593,7 @@ type internal FsiDynamicCompiler let ilxGenerator = istate.ilxGenerator let isIncrementalFragment = true let showTypes = false - let declaredImpls = [impl] + let declaredImpls = [|impl|] let codegenResults, optEnv, fragName = ProcessTypedImpl(errorLogger, istate.optEnv, istate.tcState, tcConfig, false, EmptyTopAttrs, prefix, isIncrementalFragment, declaredImpls, ilxGenerator) let istate, declaredImpls = ProcessCodegenResults(ctok, errorLogger, istate, optEnv, istate.tcState, tcConfig, prefix, showTypes, isIncrementalFragment, fragName, declaredImpls, ilxGenerator, codegenResults) let newState = { istate with tcState = istate.tcState.NextStateAfterIncrementalFragment tcEnvAtEndOfLastInput } diff --git a/src/fsharp/service/FSharpCheckerResults.fs b/src/fsharp/service/FSharpCheckerResults.fs index 31263f4e282..a3967b8ffd3 100644 --- a/src/fsharp/service/FSharpCheckerResults.fs +++ b/src/fsharp/service/FSharpCheckerResults.fs @@ -1514,7 +1514,7 @@ module internal ParseAndCheckFile = fileName.Equals(options.LastFileName, StringComparison.CurrentCultureIgnoreCase) || CompileOps.IsScript(fileName) let isExe = options.IsExe - try Some (ParseInput(lexfun, errHandler.ErrorLogger, lexbuf, None, fileName, (isLastCompiland, isExe))) + try Some (ParseInput(lexfun, errHandler.ErrorLogger, lexbuf, None, fileName, isLastCompiland, isExe)) with e -> errHandler.ErrorLogger.StopProcessingRecovery e Range.range0 // don't re-raise any exceptions, we must return None. None) @@ -1669,7 +1669,7 @@ module internal ParseAndCheckFile = with e -> errorR e let mty = Construct.NewEmptyModuleOrNamespaceType Namespace - return Some((tcState.TcEnvFromSignatures, EmptyTopAttrs, [], [ mty ]), tcState) + return Some((tcState.TcEnvFromSignatures, EmptyTopAttrs, Array.Empty(), [| mty |]), tcState) } let errors = errHandler.CollectedDiagnostics @@ -1678,7 +1678,7 @@ module internal ParseAndCheckFile = match resOpt with | Some ((tcEnvAtEnd, _, implFiles, ccuSigsForFiles), tcState) -> TypeCheckInfo(tcConfig, tcGlobals, - List.head ccuSigsForFiles, + Array.head ccuSigsForFiles, tcState.Ccu, tcImports, tcEnvAtEnd.AccessRights, @@ -1690,7 +1690,7 @@ module internal ParseAndCheckFile = loadClosure, reactorOps, textSnapshotInfo, - List.tryHead implFiles, + Array.tryHead implFiles, sink.GetOpenDeclarations()) |> Result.Ok | None -> @@ -2011,7 +2011,7 @@ type FSharpCheckProjectResults errors: FSharpErrorInfo[], details:(TcGlobals * TcImports * CcuThunk * ModuleOrNamespaceType * TcSymbolUses list * TopAttribs option * CompileOps.IRawFSharpAssemblyData option * ILAssemblyRef * - AccessorDomain * TypedImplFile list option * string[]) option) = + AccessorDomain * TypedImplFile[] option * string[]) option) = let getDetails() = match details with @@ -2036,7 +2036,7 @@ type FSharpCheckProjectResults let (tcGlobals, tcImports, thisCcu, _ccuSig, _tcSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles) = getDetails() let mimpls = match tcAssemblyExpr with - | None -> [] + | None -> Array.Empty() | Some mimpls -> mimpls tcGlobals, thisCcu, tcImports, mimpls @@ -2045,7 +2045,7 @@ type FSharpCheckProjectResults let (tcGlobals, tcImports, thisCcu, ccuSig, _tcSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles) = getDetails() let mimpls = match tcAssemblyExpr with - | None -> [] + | None -> Array.Empty() | Some mimpls -> mimpls FSharpAssemblyContents(tcGlobals, thisCcu, Some ccuSig, tcImports, mimpls) @@ -2054,7 +2054,7 @@ type FSharpCheckProjectResults let (tcGlobals, tcImports, thisCcu, ccuSig, _tcSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles) = getDetails() let mimpls = match tcAssemblyExpr with - | None -> [] + | None -> Array.Empty() | Some mimpls -> mimpls let outfile = "" // only used if tcConfig.writeTermsToFiles is true let importMap = tcImports.GetImportMap() @@ -2063,8 +2063,7 @@ type FSharpCheckProjectResults let optimizedImpls, _optimizationData, _ = ApplyAllOptimizations (tcConfig, tcGlobals, (LightweightTcValForUsingInBuildMethodCall tcGlobals), outfile, importMap, false, optEnv0, thisCcu, mimpls) let mimpls = match optimizedImpls with - | TypedAssemblyAfterOptimization files -> - files |> List.map fst + | TypedAssemblyAfterOptimization files -> Array.map fst files FSharpAssemblyContents(tcGlobals, thisCcu, Some ccuSig, tcImports, mimpls) diff --git a/src/fsharp/service/FSharpCheckerResults.fsi b/src/fsharp/service/FSharpCheckerResults.fsi index 12be0190a35..e64094aa2c9 100644 --- a/src/fsharp/service/FSharpCheckerResults.fsi +++ b/src/fsharp/service/FSharpCheckerResults.fsi @@ -357,7 +357,7 @@ type public FSharpCheckProjectResults = tcConfigOption: TcConfig option * keepAssemblyContents: bool * errors: FSharpErrorInfo[] * - details:(TcGlobals * TcImports * CcuThunk * ModuleOrNamespaceType * TcSymbolUses list * TopAttribs option * IRawFSharpAssemblyData option * ILAssemblyRef * AccessorDomain * TypedImplFile list option * string[]) option + details:(TcGlobals * TcImports * CcuThunk * ModuleOrNamespaceType * TcSymbolUses list * TopAttribs option * IRawFSharpAssemblyData option * ILAssemblyRef * AccessorDomain * TypedImplFile[] option * string[]) option -> FSharpCheckProjectResults module internal ParseAndCheckFile = diff --git a/src/fsharp/service/IncrementalBuild.fs b/src/fsharp/service/IncrementalBuild.fs index f60d85adfc1..6537c409813 100755 --- a/src/fsharp/service/IncrementalBuild.fs +++ b/src/fsharp/service/IncrementalBuild.fs @@ -450,12 +450,12 @@ module internal IncrementalBuild = [] type BuildInput = - | Vector of INode * obj list + | Vector of INode * obj[] | Scalar of INode * obj /// Declare a named scalar output. static member ScalarInput (node: Scalar<'T>, value: 'T) = BuildInput.Scalar(node, box value) - static member VectorInput(node: Vector<'T>, values: 'T list) = BuildInput.Vector(node, List.map box values) + static member VectorInput(node: Vector<'T>, values: 'T[]) = BuildInput.Vector(node, Array.map box values) let AvailableAllResultsOfExpr bt expr = @@ -487,8 +487,8 @@ module internal IncrementalBuild = | BuildInput.Scalar _ -> () | BuildInput.Vector (node, values) -> if node.Name = n then - let results = values|>List.mapi(fun i value->i, Available (value, now, BoundInputVector)) - yield VectorResult(ResultVector(values.Length, DateTime.MinValue, results|>Map.ofList)) ] + let results = values |> Array.mapi (fun i value -> i, Available (value, now, BoundInputVector)) + yield VectorResult(ResultVector(values.Length, DateTime.MinValue, results |> Map.ofArray)) ] List.foldBack (Map.add id) matches results | VectorScanLeft(_, _, a, i, _) ->ApplyVectorExpr(i, applyScalarExpr(a, results)) | VectorMap(_, _, i, _) @@ -1235,12 +1235,13 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput let mutable currentTcImportsOpt = None // Check for the existence of loaded sources and prepend them to the sources list if present. - let sourceFiles = tcConfig.GetAvailableLoadedSources() @ (sourceFiles |>List.map (fun s -> rangeStartup, s)) + let loadedSourcesFiles = tcConfig.GetAvailableLoadedSources() |> Array.map snd + let sourceFiles = Array.append loadedSourcesFiles sourceFiles // Mark up the source files with an indicator flag indicating if they are the last source file in the project let sourceFiles = - let flags, isExe = tcConfig.ComputeCanContainEntryPoint(sourceFiles |> List.map snd) - ((sourceFiles, flags) ||> List.map2 (fun (m, nm) flag -> (m, nm, (flag, isExe)))) + let flags, isExe = tcConfig.ComputeCanContainEntryPoint(sourceFiles) + ((sourceFiles, flags) ||> Array.map2 (fun nm flag -> (nm, flag, isExe))) let defaultTimeStamp = DateTime.UtcNow @@ -1256,7 +1257,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput let allDependencies = [| yield! basicDependencies - for (_, f, _) in sourceFiles do + for (f, _, _) in sourceFiles do yield f |] //---------------------------------------------------- @@ -1265,13 +1266,13 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput /// This is a build task function that gets placed into the build rules as the computation for a VectorStamp /// /// Get the timestamp of the given file name. - let StampFileNameTask (cache: TimeStampCache) _ctok (_m: range, filename: string, _isLastCompiland) = + let StampFileNameTask (cache: TimeStampCache) _ctok (filename: string, _isLastCompiland, _isExe) = cache.GetFileTimeStamp filename /// This is a build task function that gets placed into the build rules as the computation for a VectorMap /// /// Parse the given file and return the given input. - let ParseTask ctok (sourceRange: range, filename: string, isLastCompiland) = + let ParseTask ctok (filename: string, isLastCompiland, isExe) = DoesNotRequireCompilerThreadTokenAndCouldPossiblyBeMadeConcurrent ctok let errorLogger = CompilationErrorLogger("ParseTask", tcConfig.errorSeverityOptions) @@ -1280,10 +1281,10 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput try IncrementalBuilderEventTesting.MRU.Add(IncrementalBuilderEventTesting.IBEParsed filename) - let input = ParseOneInputFile(tcConfig, lexResourceManager, [], filename, isLastCompiland, errorLogger, (*retryLocked*)true) + let input = ParseOneInputFile(tcConfig, lexResourceManager, [], filename, isLastCompiland, isExe, errorLogger, (*retryLocked*)true) fileParsed.Trigger filename - input, sourceRange, filename, errorLogger.GetErrors () + input, filename, errorLogger.GetErrors () with exn -> let msg = sprintf "unexpected failure in IncrementalFSharpBuild.Parse\nerror = %s" (exn.ToString()) System.Diagnostics.Debug.Assert(false, msg) @@ -1375,7 +1376,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput /// Type check all files. let TypeCheckTask ctok (tcAcc: TypeCheckAccumulator) input: Eventually = match input with - | Some input, _sourceRange, filename, parseErrors-> + | Some input, filename, parseErrors-> IncrementalBuilderEventTesting.MRU.Add(IncrementalBuilderEventTesting.IBETypechecked filename) let capturingErrorLogger = CompilationErrorLogger("TypeCheckTask", tcConfig.errorSeverityOptions) let errorLogger = GetErrorLoggerFilteringByScopedPragmas(false, GetScopedPragmasForInput input, capturingErrorLogger) @@ -1480,7 +1481,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput // Finish the checking let (_tcEnvAtEndOfLastFile, topAttrs, mimpls, _), tcState = - let results = tcStates |> List.ofArray |> List.map (fun acc-> acc.tcEnvAtEndOfFile, defaultArg acc.topAttribs EmptyTopAttrs, acc.latestImplFile, acc.latestCcuSigForFile) + let results = tcStates |> Array.map (fun acc-> acc.tcEnvAtEndOfFile, defaultArg acc.topAttribs EmptyTopAttrs, acc.latestImplFile, acc.latestCcuSigForFile) TypeCheckMultipleInputsFinish (results, finalAcc.tcState) let ilAssemRef, tcAssemblyDataOpt, tcAssemblyExprOpt = @@ -1553,7 +1554,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput // START OF BUILD DESCRIPTION // Inputs - let fileNamesNode = InputVector "FileNames" + let fileNamesNode = InputVector "FileNames" let referencedAssembliesNode = InputVector*(TimeStampCache -> CompilationThreadToken -> DateTime)> "ReferencedAssemblies" // Build @@ -1695,7 +1696,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput member __.TryGetSlotOfFileName(filename: string) = // Get the slot of the given file and force it to build. - let CompareFileNames (_, f2, _) = + let CompareFileNames (f2, _, _) = let result = String.Compare(filename, f2, StringComparison.CurrentCultureIgnoreCase)=0 || String.Compare(FileSystem.GetFullPathShim filename, FileSystem.GetFullPathShim f2, StringComparison.CurrentCultureIgnoreCase)=0 @@ -1736,7 +1737,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput return ParseTask ctok results } - member __.SourceFiles = sourceFiles |> List.map (fun (_, f, _) -> f) + member __.SourceFiles = sourceFiles |> Array.map (fun (f, _, _) -> f) /// CreateIncrementalBuilder (for background type checking). Note that fsc.fs also /// creates an incremental builder used by the command line compiler. @@ -1744,7 +1745,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput (ctok, legacyReferenceResolver, defaultFSharpBinariesDir, frameworkTcImportsCache: FrameworkImportsCache, loadClosureOpt: LoadClosure option, - sourceFiles: string list, + sourceFiles: string[], commandLineArgs: string list, projectReferences, projectDirectory, useScriptResolutionRules, keepAssemblyContents, @@ -1768,7 +1769,7 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput let resourceManager = new Lexhelp.LexResourceManager() /// Create a type-check configuration - let tcConfigB, sourceFilesNew = + let tcConfigB, (sourceFilesNew: string[]) = let getSwitchValue switchString = match commandLineArgs |> Seq.tryFindIndex(fun s -> s.StartsWithOrdinal switchString) with @@ -1856,12 +1857,12 @@ type IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInput // Return the disposable object that cleans up use _holder = new CompilationGlobalsScope(errorLogger, BuildPhase.Parameter) - [ for r in nonFrameworkResolutions do - let fileName = r.resolvedPath - yield (Choice1Of2 fileName, (fun (cache: TimeStampCache) _ctok -> cache.GetFileTimeStamp fileName)) + [| for r in nonFrameworkResolutions do + let fileName = r.resolvedPath + yield (Choice1Of2 fileName, (fun (cache: TimeStampCache) _ctok -> cache.GetFileTimeStamp fileName)) - for pr in projectReferences do - yield Choice2Of2 pr, (fun (cache: TimeStampCache) ctok -> cache.GetProjectReferenceTimeStamp (pr, ctok)) ] + for pr in projectReferences do + yield Choice2Of2 pr, (fun (cache: TimeStampCache) ctok -> cache.GetProjectReferenceTimeStamp (pr, ctok)) |] let builder = new IncrementalBuilder(tcGlobals, frameworkTcImports, nonFrameworkAssemblyInputs, nonFrameworkResolutions, unresolvedReferences, diff --git a/src/fsharp/service/IncrementalBuild.fsi b/src/fsharp/service/IncrementalBuild.fsi index e9f945cd970..1cff16372d5 100755 --- a/src/fsharp/service/IncrementalBuild.fsi +++ b/src/fsharp/service/IncrementalBuild.fsi @@ -100,7 +100,7 @@ type internal IncrementalBuilder = member TcConfig : TcConfig /// The full set of source files including those from options - member SourceFiles : string list + member SourceFiles : string[] /// Raised just before a file is type-checked, to invalidate the state of the file in VS and force VS to request a new direct typecheck of the file. /// The incremental builder also typechecks the file (error and intellisense results from the background builder are not @@ -167,7 +167,7 @@ type internal IncrementalBuilder = /// This may be a long-running operation. /// // TODO: make this an Eventually (which can be scheduled) or an Async (which can be cancelled) - member GetCheckResultsAndImplementationsForProject : CompilationThreadToken -> Cancellable + member GetCheckResultsAndImplementationsForProject : CompilationThreadToken -> Cancellable /// Get the logical time stamp that is associated with the output of the project if it were gully built immediately member GetLogicalTimeStampForProject: TimeStampCache * CompilationThreadToken -> DateTime @@ -178,9 +178,9 @@ type internal IncrementalBuilder = /// Await the untyped parse results for a particular slot in the vector of parse results. /// /// This may be a marginally long-running operation (parses are relatively quick, only one file needs to be parsed) - member GetParseResultsForFile : CompilationThreadToken * filename:string -> Cancellable + member GetParseResultsForFile : CompilationThreadToken * filename:string -> Cancellable - static member TryCreateBackgroundBuilderForProjectOptions : CompilationThreadToken * ReferenceResolver.Resolver * defaultFSharpBinariesDir: string * FrameworkImportsCache * scriptClosureOptions:LoadClosure option * sourceFiles:string list * commandLineArgs:string list * projectReferences: IProjectReference list * projectDirectory:string * useScriptResolutionRules:bool * keepAssemblyContents: bool * keepAllBackgroundResolutions: bool * maxTimeShareMilliseconds: int64 * tryGetMetadataSnapshot: ILBinaryReader.ILReaderTryGetMetadataSnapshot * suggestNamesForErrors: bool * keepAllBackgroundSymbolUses: bool * enableBackgroundItemKeyStoreAndSemanticClassification: bool -> Cancellable + static member TryCreateBackgroundBuilderForProjectOptions : CompilationThreadToken * ReferenceResolver.Resolver * defaultFSharpBinariesDir: string * FrameworkImportsCache * scriptClosureOptions:LoadClosure option * sourceFiles:string[] * commandLineArgs:string list * projectReferences: IProjectReference list * projectDirectory:string * useScriptResolutionRules:bool * keepAssemblyContents: bool * keepAllBackgroundResolutions: bool * maxTimeShareMilliseconds: int64 * tryGetMetadataSnapshot: ILBinaryReader.ILReaderTryGetMetadataSnapshot * suggestNamesForErrors: bool * keepAllBackgroundSymbolUses: bool * enableBackgroundItemKeyStoreAndSemanticClassification: bool -> Cancellable /// Generalized Incremental Builder. This is exposed only for unit testing purposes. module internal IncrementalBuild = @@ -258,7 +258,7 @@ module internal IncrementalBuild = type BuildInput = /// Declare a named scalar output. static member ScalarInput: node:Scalar<'T> * value: 'T -> BuildInput - static member VectorInput: node:Vector<'T> * value: 'T list -> BuildInput + static member VectorInput: node:Vector<'T> * value: 'T[] -> BuildInput /// Declare build outputs and bind them to real values. /// Only required for unit testing. diff --git a/src/fsharp/service/service.fs b/src/fsharp/service/service.fs index 246f6d7440e..8bcd199e17a 100644 --- a/src/fsharp/service/service.fs +++ b/src/fsharp/service/service.fs @@ -54,7 +54,7 @@ type FSharpProjectOptions = UseScriptResolutionRules : bool LoadTime : System.DateTime UnresolvedReferences : UnresolvedReferencesSet option - OriginalLoadReferences: (range * string * string) list + OriginalLoadReferences: (range * string * string)[] ExtraProjectInfo : obj option Stamp : int64 option } @@ -303,7 +303,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC let loadClosure = scriptClosureCacheLock.AcquireLock (fun ltok -> scriptClosureCache.TryGet (ltok, options)) let! builderOpt, diagnostics = IncrementalBuilder.TryCreateBackgroundBuilderForProjectOptions - (ctok, legacyReferenceResolver, FSharpCheckerResultsSettings.defaultFSharpBinariesDir, frameworkTcImportsCache, loadClosure, Array.toList options.SourceFiles, + (ctok, legacyReferenceResolver, FSharpCheckerResultsSettings.defaultFSharpBinariesDir, frameworkTcImportsCache, loadClosure, options.SourceFiles, Array.toList options.OtherOptions, projectReferences, options.ProjectDirectory, options.UseScriptResolutionRules, keepAssemblyContents, keepAllBackgroundResolutions, FSharpCheckerResultsSettings.maxTimeShareMilliseconds, tryGetMetadataSnapshot, suggestNamesForErrors, keepAllBackgroundSymbolUses, enableBackgroundItemKeyStoreAndSemanticClassification) @@ -450,7 +450,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC match builderOpt with | None -> return FSharpParseFileResults(creationErrors, None, true, [| |]) | Some builder -> - let! parseTreeOpt,_,_,parseErrors = builder.GetParseResultsForFile (ctok, filename) + let! parseTreeOpt,_,parseErrors = builder.GetParseResultsForFile (ctok, filename) let errors = [| yield! creationErrors; yield! ErrorHelpers.CreateErrorInfos (builder.TcConfig.errorSeverityOptions, false, filename, parseErrors, suggestNamesForErrors) |] return FSharpParseFileResults(errors = errors, input = parseTreeOpt, parseHadErrors = false, dependencyFiles = builder.AllDependenciesDeprecated) } @@ -536,7 +536,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC parseResults.Errors, keepAssemblyContents, suggestNamesForErrors) - let parsingOptions = FSharpParsingOptions.FromTcConfig(tcPrior.TcConfig, Array.ofList builder.SourceFiles, options.UseScriptResolutionRules) + let parsingOptions = FSharpParsingOptions.FromTcConfig(tcPrior.TcConfig, builder.SourceFiles, options.UseScriptResolutionRules) reactor.SetPreferredUILang tcPrior.TcConfig.preferredUiLang bc.RecordTypeCheckFileInProjectResults(fileName, options, parsingOptions, parseResults, fileVersion, tcPrior.TimeStamp, Some checkAnswer, sourceText.GetHashCode()) return checkAnswer @@ -654,7 +654,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC let! tcPrior = execWithReactorAsync <| fun ctok -> builder.GetCheckResultsBeforeFileInProject (ctok, filename) // Do the parsing. - let parsingOptions = FSharpParsingOptions.FromTcConfig(builder.TcConfig, Array.ofList (builder.SourceFiles), options.UseScriptResolutionRules) + let parsingOptions = FSharpParsingOptions.FromTcConfig(builder.TcConfig, builder.SourceFiles, options.UseScriptResolutionRules) reactor.SetPreferredUILang tcPrior.TcConfig.preferredUiLang let parseErrors, parseTreeOpt, anyErrors = ParseAndCheckFile.parseFile (sourceText, filename, parsingOptions, userOpName, suggestNamesForErrors) let parseResults = FSharpParseFileResults(parseErrors, parseTreeOpt, anyErrors, builder.AllDependenciesDeprecated) @@ -678,7 +678,7 @@ type BackgroundCompiler(legacyReferenceResolver, projectCacheSize, keepAssemblyC let typedResults = FSharpCheckFileResults.MakeEmpty(filename, creationErrors, reactorOps, keepAssemblyContents) return (parseResults, typedResults) | Some builder -> - let! (parseTreeOpt, _, _, untypedErrors) = builder.GetParseResultsForFile (ctok, filename) + let! (parseTreeOpt, _, untypedErrors) = builder.GetParseResultsForFile (ctok, filename) let! tcProj = builder.GetCheckResultsAfterFileInProject (ctok, filename) let errorOptions = builder.TcConfig.errorSeverityOptions let untypedErrors = [| yield! creationErrors; yield! ErrorHelpers.CreateErrorInfos (errorOptions, false, filename, untypedErrors, suggestNamesForErrors) |] @@ -1014,7 +1014,7 @@ type FSharpChecker(legacyReferenceResolver, ic.MatchBraces(filename, SourceText.ofString source, parsingOptions, userOpName) member ic.GetParsingOptionsFromProjectOptions(options): FSharpParsingOptions * _ = - let sourceFiles = List.ofArray options.SourceFiles + let sourceFiles = options.SourceFiles let argv = List.ofArray options.OtherOptions ic.GetParsingOptionsFromCommandLineArgs(sourceFiles, argv, options.UseScriptResolutionRules) @@ -1053,7 +1053,7 @@ type FSharpChecker(legacyReferenceResolver, return CompileHelpers.compileFromArgs (ctok, argv, legacyReferenceResolver, None, None) }) - member __.Compile (ast:ParsedInput list, assemblyName:string, outFile:string, dependencies:string list, ?pdbFile:string, ?executable:bool, ?noframework:bool, ?userOpName: string) = + member __.Compile (ast:ParsedInput[], assemblyName:string, outFile:string, dependencies:string list, ?pdbFile:string, ?executable:bool, ?noframework:bool, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" backgroundCompiler.Reactor.EnqueueAndAwaitOpAsync (userOpName, "Compile", assemblyName, fun ctok -> cancellable { @@ -1090,7 +1090,7 @@ type FSharpChecker(legacyReferenceResolver, } ) - member __.CompileToDynamicAssembly (asts:ParsedInput list, assemblyName:string, dependencies:string list, execute: (TextWriter * TextWriter) option, ?debug:bool, ?noframework:bool, ?userOpName: string) = + member __.CompileToDynamicAssembly (asts:ParsedInput[], assemblyName:string, dependencies:string list, execute: (TextWriter * TextWriter) option, ?debug:bool, ?noframework:bool, ?userOpName: string) = let userOpName = defaultArg userOpName "Unknown" backgroundCompiler.Reactor.EnqueueAndAwaitOpAsync (userOpName, "CompileToDynamicAssembly", assemblyName, fun ctok -> cancellable { @@ -1227,7 +1227,7 @@ type FSharpChecker(legacyReferenceResolver, UseScriptResolutionRules = false LoadTime = loadedTimeStamp UnresolvedReferences = None - OriginalLoadReferences=[] + OriginalLoadReferences= Array.Empty() ExtraProjectInfo=extraProjectInfo Stamp = None } @@ -1238,10 +1238,10 @@ type FSharpChecker(legacyReferenceResolver, // Apply command-line arguments and collect more source files if they are in the arguments let sourceFilesNew = ApplyCommandLineArgs(tcConfigBuilder, initialSourceFiles, argv) - FSharpParsingOptions.FromTcConfigBuilder(tcConfigBuilder, Array.ofList sourceFilesNew, isInteractive), errorScope.Diagnostics + FSharpParsingOptions.FromTcConfigBuilder(tcConfigBuilder, sourceFilesNew, isInteractive), errorScope.Diagnostics member ic.GetParsingOptionsFromCommandLineArgs(argv, ?isInteractive: bool) = - ic.GetParsingOptionsFromCommandLineArgs([], argv, ?isInteractive=isInteractive) + ic.GetParsingOptionsFromCommandLineArgs(Array.Empty(), argv, ?isInteractive=isInteractive) /// Begin background parsing the given project. member __.StartBackgroundCompile(options, ?userOpName) = diff --git a/src/fsharp/service/service.fsi b/src/fsharp/service/service.fsi index cb414c87ab1..ac1595a0795 100755 --- a/src/fsharp/service/service.fsi +++ b/src/fsharp/service/service.fsi @@ -51,8 +51,8 @@ type public FSharpProjectOptions = /// Unused in this API and should be 'None' when used as user-specified input UnresolvedReferences : UnresolvedReferencesSet option - /// Unused in this API and should be '[]' when used as user-specified input - OriginalLoadReferences: (range * string * string) list + /// Unused in this API and should be empty when used as user-specified input + OriginalLoadReferences: (range * string * string)[] /// Extra information passed back on event trigger ExtraProjectInfo : obj option @@ -245,7 +245,7 @@ type public FSharpChecker = /// /// Initial source files list. Additional files may be added during argv evaluation. /// The command line arguments for the project build. - member GetParsingOptionsFromCommandLineArgs: sourceFiles: string list * argv: string list * ?isInteractive: bool -> FSharpParsingOptions * FSharpErrorInfo list + member GetParsingOptionsFromCommandLineArgs: sourceFiles: string[] * argv: string list * ?isInteractive: bool -> FSharpParsingOptions * FSharpErrorInfo list /// /// Get the FSharpParsingOptions implied by a set of command line arguments. @@ -315,7 +315,7 @@ type public FSharpChecker = /// TypeCheck and compile provided AST /// /// An optional string used for tracing compiler operations associated with this request. - member Compile: ast:ParsedInput list * assemblyName:string * outFile:string * dependencies:string list * ?pdbFile:string * ?executable:bool * ?noframework:bool * ?userOpName: string -> Async + member Compile: ast:ParsedInput[] * assemblyName:string * outFile:string * dependencies:string list * ?pdbFile:string * ?executable:bool * ?noframework:bool * ?userOpName: string -> Async /// /// Compiles to a dynamic assembly using the given flags. @@ -336,7 +336,7 @@ type public FSharpChecker = /// TypeCheck and compile provided AST /// /// An optional string used for tracing compiler operations associated with this request. - member CompileToDynamicAssembly: ast:ParsedInput list * assemblyName:string * dependencies:string list * execute:(TextWriter * TextWriter) option * ?debug:bool * ?noframework:bool * ?userOpName: string -> Async + member CompileToDynamicAssembly: ast:ParsedInput[] * assemblyName:string * dependencies:string list * execute:(TextWriter * TextWriter) option * ?debug:bool * ?noframework:bool * ?userOpName: string -> Async /// /// Try to get type check results for a file. This looks up the results of recent type checks of the diff --git a/src/fsharp/symbols/Exprs.fs b/src/fsharp/symbols/Exprs.fs index 17290528587..783f3c42707 100644 --- a/src/fsharp/symbols/Exprs.fs +++ b/src/fsharp/symbols/Exprs.fs @@ -1232,7 +1232,7 @@ module FSharpExprConvert = /// The contents of the F# assembly as provided through the compiler API -type FSharpAssemblyContents(cenv: SymbolEnv, mimpls: TypedImplFile list) = +type FSharpAssemblyContents(cenv: SymbolEnv, mimpls: TypedImplFile[]) = new (g, thisCcu, thisCcuType, tcImports, mimpls) = FSharpAssemblyContents(SymbolEnv(g, thisCcu, thisCcuType, tcImports), mimpls) diff --git a/src/fsharp/symbols/Exprs.fsi b/src/fsharp/symbols/Exprs.fsi index 2d2a78370ee..b1b6cbc9335 100644 --- a/src/fsharp/symbols/Exprs.fsi +++ b/src/fsharp/symbols/Exprs.fsi @@ -11,7 +11,7 @@ open FSharp.Compiler.TypedTree /// Represents the definitional contents of an assembly, as seen by the F# language type public FSharpAssemblyContents = - internal new : tcGlobals: TcGlobals * thisCcu: CcuThunk * thisCcuType: ModuleOrNamespaceType option * tcImports: TcImports * mimpls: TypedImplFile list -> FSharpAssemblyContents + internal new : tcGlobals: TcGlobals * thisCcu: CcuThunk * thisCcuType: ModuleOrNamespaceType option * tcImports: TcImports * mimpls: TypedImplFile[] -> FSharpAssemblyContents /// The contents of the implementation files in the assembly member ImplementationFiles: FSharpImplementationFileContents list diff --git a/tests/service/FileSystemTests.fs b/tests/service/FileSystemTests.fs index 59bb29f0553..2efb17564a7 100644 --- a/tests/service/FileSystemTests.fs +++ b/tests/service/FileSystemTests.fs @@ -106,7 +106,7 @@ let ``FileSystem compilation test``() = UseScriptResolutionRules = true LoadTime = System.DateTime.Now // Not 'now', we don't want to force reloading UnresolvedReferences = None - OriginalLoadReferences = [] + OriginalLoadReferences = [||] ExtraProjectInfo = None Stamp = None } diff --git a/tests/service/MultiProjectAnalysisTests.fs b/tests/service/MultiProjectAnalysisTests.fs index 6d915d486a8..b499e51188b 100644 --- a/tests/service/MultiProjectAnalysisTests.fs +++ b/tests/service/MultiProjectAnalysisTests.fs @@ -895,13 +895,13 @@ let ``Type provider project references should not throw exceptions`` () = UseScriptResolutionRules = false; LoadTime = System.DateTime.Now UnresolvedReferences = None; - OriginalLoadReferences = []; + OriginalLoadReferences = [||]; ExtraProjectInfo = None;})|]; IsIncompleteTypeCheckEnvironment = false; UseScriptResolutionRules = false; LoadTime = System.DateTime.Now UnresolvedReferences = None; - OriginalLoadReferences = []; + OriginalLoadReferences = [||]; ExtraProjectInfo = None;} //printfn "options: %A" options @@ -990,7 +990,7 @@ let ``Projects creating generated types should not utilize cross-project-referen UseScriptResolutionRules = false; LoadTime = System.DateTime.Now UnresolvedReferences = None; - OriginalLoadReferences = []; + OriginalLoadReferences = [||]; Stamp = None; ExtraProjectInfo = None;})|]; IsIncompleteTypeCheckEnvironment = false; @@ -998,7 +998,7 @@ let ``Projects creating generated types should not utilize cross-project-referen LoadTime = System.DateTime.Now UnresolvedReferences = None; Stamp = None; - OriginalLoadReferences = []; + OriginalLoadReferences = [||]; ExtraProjectInfo = None;} //printfn "options: %A" options let fileName = __SOURCE_DIRECTORY__ + @"/data/TypeProvidersBug/TestConsole/Program.fs"