Skip to content

Commit cb4c558

Browse files
committed
Fable parsing update
1 parent bd3bb77 commit cb4c558

File tree

5 files changed

+146
-45
lines changed

5 files changed

+146
-45
lines changed

fcs/build.fsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ let isMono = false
2121
#endif
2222

2323

24-
let dotnetExePath = DotNetCli.InstallDotNetSDK "2.1.402"
24+
let dotnetExePath = DotNetCli.InstallDotNetSDK "2.1.403"
2525

2626
let runDotnet workingDir args =
2727
let result =

fcs/fcs-fable/service_shim.fs

Lines changed: 121 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ open Microsoft.FSharp.Control
1515
open System
1616
open System.Text
1717
open System.Threading
18+
open System.Collections.Concurrent
1819
open System.Collections.Generic
1920

2021
open Microsoft.FSharp.Compiler
@@ -50,16 +51,17 @@ open Microsoft.FSharp.Compiler.TypeChecker
5051
// InteractiveChecker
5152
//-------------------------------------------------------------------------
5253

53-
type InteractiveChecker internal (tcConfig, tcGlobals, tcImports, tcState, ctok, reactorOps) =
54+
type InteractiveChecker internal (tcConfig, tcGlobals, tcImports, tcInitialState, ctok, reactorOps, moduleNamesDict) =
55+
let userOpName = "Unknown"
5456

55-
static member Create(references: string[], readAllBytes: string -> byte[]) =
57+
static member Create(references: string[], readAllBytes: string -> byte[], defines: string[]) =
5658

5759
let GetSignatureData ((filename:string), ilScopeRef, (ilModule:ILModuleDef option), (bytes:byte[])) =
5860
TastPickle.unpickleObjWithDanglingCcus filename ilScopeRef ilModule TastPickle.unpickleCcuInfo bytes
5961
let GetOptimizationData ((filename:string), ilScopeRef, (ilModule:ILModuleDef option), (bytes:byte[])) =
6062
TastPickle.unpickleObjWithDanglingCcus filename ilScopeRef ilModule Optimizer.u_CcuOptimizationInfo bytes
6163

62-
let tcConfig = TcConfig (optimize = true)
64+
let tcConfig = TcConfig (optimize = true, defines = Array.toList defines)
6365
let tcImports = TcImports ()
6466
let ilGlobals = IL.EcmaMscorlibILGlobals
6567

@@ -142,7 +144,9 @@ type InteractiveChecker internal (tcConfig, tcGlobals, tcImports, tcState, ctok,
142144
let fileName = ilModule.Name
143145
let ilScopeRef = ILScopeRef.Assembly (mkSimpleAssRef ccuName)
144146
let invalidateCcu = new Event<_>()
145-
let ccu = Import.ImportILAssembly(tcImports.GetImportMap,m,auxModuleLoader,ilScopeRef,tcConfig.implicitIncludeDir,Some fileName,ilModule,invalidateCcu.Publish)
147+
let ccu = Import.ImportILAssembly(
148+
tcImports.GetImportMap, m, auxModuleLoader, ilScopeRef,
149+
tcConfig.implicitIncludeDir, Some fileName, ilModule, invalidateCcu.Publish)
146150
let ccuInfo = mkCcuInfo ilGlobals ilScopeRef ilModule ccu
147151
ccuInfo, None
148152

@@ -220,7 +224,10 @@ type InteractiveChecker internal (tcConfig, tcGlobals, tcImports, tcState, ctok,
220224

221225
// search over all imported CCUs for each cached type
222226
let ccuHasType (ccu: CcuThunk) (nsname: string list) (tname: string) =
223-
match (Some ccu.Contents, nsname) ||> List.fold (fun entityOpt n -> match entityOpt with None -> None | Some entity -> entity.ModuleOrNamespaceType.AllEntitiesByCompiledAndLogicalMangledNames.TryFind n) with
227+
match (Some ccu.Contents, nsname) ||> List.fold (fun entityOpt n ->
228+
match entityOpt with
229+
| None -> None
230+
| Some entity -> entity.ModuleOrNamespaceType.AllEntitiesByCompiledAndLogicalMangledNames.TryFind n) with
224231
| Some ns ->
225232
match Map.tryFind tname ns.ModuleOrNamespaceType.TypesByMangledName with
226233
| Some _ -> true
@@ -256,8 +263,8 @@ type InteractiveChecker internal (tcConfig, tcGlobals, tcImports, tcState, ctok,
256263

257264
let assemblyName = "Project"
258265
let ccus = ccuInfos |> List.map (fun x -> x.FSharpViewOfMetadata, x.AssemblyAutoOpenAttributes, x.AssemblyInternalsVisibleToAttributes)
259-
let tcEnv = CreateInitialTcEnv (tcGlobals, amap, rng, assemblyName, ccus)
260-
let tcState = GetInitialTcState (rangeStartup, assemblyName, tcConfig, tcGlobals, tcImports, niceNameGen, tcEnv)
266+
let tcInitialEnv = CreateInitialTcEnv (tcGlobals, amap, rng, assemblyName, ccus)
267+
let tcInitialState = GetInitialTcState (rangeStartup, assemblyName, tcConfig, tcGlobals, tcImports, niceNameGen, tcInitialEnv)
261268
let ctok = CompilationThreadToken()
262269

263270
let reactorOps =
@@ -266,44 +273,118 @@ type InteractiveChecker internal (tcConfig, tcGlobals, tcImports, tcState, ctok,
266273
async.Return (Cancellable.runWithoutCancellation (op ctok))
267274
member __.EnqueueOp (userOpName, opName, opArg, op) = (op ctok) }
268275

269-
InteractiveChecker (tcConfig, tcGlobals, tcImports, tcState, ctok, reactorOps)
276+
// for de-duplicating module names
277+
let moduleNamesDict = ConcurrentDictionary<string, Set<string>>()
278+
279+
InteractiveChecker (tcConfig, tcGlobals, tcImports, tcInitialState, ctok, reactorOps, moduleNamesDict)
270280

271-
member x.ParseScript (mainInputFileName, source) =
272-
let userOpName = "Unknown"
273-
let filename = mainInputFileName
274-
// Note: projectSourceFiles is only used to compute isLastCompiland, and is ignored if Build.IsScript(mainInputFileName) is true (which it is in this case).
275-
let parsingOptions = FSharpParsingOptions.FromTcConfig(tcConfig, [| filename |], false)
276-
let parseErrors, inputOpt, anyErrors = Parser.parseFile (source, filename, parsingOptions, userOpName)
281+
member private x.MakeProjectResults (projectFileName: string, parseResults: FSharpParseFileResults[], tcState: TcState, errors: FSharpErrorInfo[],
282+
symbolUses: TcSymbolUses list, topAttrsOpt: TopAttribs option, tcImplFilesOpt: TypedImplFile list option) =
283+
let assemblyRef = mkSimpleAssRef "stdin"
284+
let assemblyDataOpt = None
285+
let access = tcState.TcEnvFromImpls.AccessRights
286+
let dependencyFiles = parseResults |> Seq.map (fun x -> x.DependencyFiles) |> Array.concat
287+
let details = (tcGlobals, tcImports, tcState.Ccu, tcState.CcuSig, symbolUses, topAttrsOpt, assemblyDataOpt, assemblyRef, access, tcImplFilesOpt, dependencyFiles)
288+
FSharpCheckProjectResults (projectFileName, Some tcConfig, true, errors, Some details)
289+
290+
member private x.ParseScript (filename: string, source: string) =
291+
let parsingOptions = FSharpParsingOptions.FromTcConfig(tcConfig, [| filename |], true)
292+
let parseErrors, parseTreeOpt, anyErrors = Parser.parseFile (source, filename, parsingOptions, userOpName)
293+
let parseTreeOpt = parseTreeOpt |> Option.map (DeduplicateParsedInputModuleName moduleNamesDict)
277294
let dependencyFiles = [||] // interactions have no dependencies
278-
let parseResults = FSharpParseFileResults(parseErrors, inputOpt, parseHadErrors = anyErrors, dependencyFiles = dependencyFiles)
279-
parseResults
295+
FSharpParseFileResults (parseErrors, parseTreeOpt, anyErrors, dependencyFiles)
280296

281-
member x.ParseAndCheckScript (mainInputFileName, source) =
282-
let parseResults = x.ParseScript (mainInputFileName, source)
297+
member x.ParseAndCheckScript (projectFileName, filename: string, source: string) =
298+
let parseResults = x.ParseScript (filename, source)
283299
let loadClosure = None
284300
let backgroundErrors = [||]
285-
let tcResults =
286-
Parser.CheckOneFile(parseResults,
287-
source,
288-
mainInputFileName,
289-
"project",
290-
tcConfig,
291-
tcGlobals,
292-
tcImports,
293-
tcState,
294-
loadClosure,
295-
backgroundErrors,
296-
reactorOps,
297-
(fun () -> true),
298-
None,
299-
"")
300-
301-
match tcResults with
301+
let checkAlive = fun () -> true
302+
let textSnapshotInfo = None
303+
let tcState = tcInitialState
304+
let tcResults = Parser.CheckOneFile(
305+
parseResults, source, filename, projectFileName, tcConfig, tcGlobals, tcImports, tcState,
306+
loadClosure, backgroundErrors, reactorOps, checkAlive, textSnapshotInfo, userOpName)
307+
match tcResults with
302308
| tcErrors, Parser.TypeCheckAborted.No scope ->
303-
let errors = [| yield! parseResults.Errors; yield! tcErrors |]
304-
let tcImplFiles = match scope.ImplementationFile with Some x -> Some [x] | None -> None
305-
let typeCheckResults = FSharpCheckFileResults (mainInputFileName, errors, Some scope, parseResults.DependencyFiles, None, reactorOps, true)
306-
let projectResults = FSharpCheckProjectResults (mainInputFileName, Some tcConfig, true, errors, Some(tcGlobals, tcImports, scope.ThisCcu, scope.CcuSigForFile, [scope.ScopeSymbolUses], None, None, mkSimpleAssRef "stdin", tcState.TcEnvFromImpls.AccessRights, tcImplFiles, parseResults.DependencyFiles))
309+
let errors = Array.append parseResults.Errors tcErrors
310+
let tcImplFilesOpt = match scope.ImplementationFile with Some x -> Some [x] | None -> None
311+
let typeCheckResults = FSharpCheckFileResults (filename, errors, Some scope, parseResults.DependencyFiles, None, reactorOps, true)
312+
let symbolUses = [scope.ScopeSymbolUses]
313+
let projectResults = x.MakeProjectResults (projectFileName, [|parseResults|], tcState, errors, symbolUses, None, tcImplFilesOpt)
307314
parseResults, typeCheckResults, projectResults
308-
| _ ->
315+
| _ ->
309316
failwith "unexpected aborted"
317+
318+
member x.ParseAndCheckProject (projectFileName, fileNames: string[], sources: string[]) =
319+
use errorScope = new ErrorScope()
320+
let sink = TcResultsSinkImpl(tcGlobals)
321+
322+
let typeCheckOneInput (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt) tcSink tcState input =
323+
//// 'use' ensures that the warning handler is restored at the end
324+
//use unwindEL = PushErrorLoggerPhaseUntilUnwind(fun oldLogger ->
325+
// GetErrorLoggerFilteringByScopedPragmas(false, GetScopedPragmasForInput(input), oldLogger) )
326+
//use unwindBP = PushThreadBuildPhaseUntilUnwind BuildPhase.TypeCheck
327+
TypeCheckOneInputEventually (checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input)
328+
|> Eventually.force ctok
329+
330+
let makeTcResult (tcState: TcState) (parseRes: FSharpParseFileResults, (tcEnvAtEnd: TcEnv, _topAttrs, implFile, ccuSigForFile)) =
331+
let filename = parseRes.FileName
332+
let loadClosure = None
333+
let checkAlive = fun () -> true
334+
let textSnapshotInfo = None
335+
let tcErrors = errorScope.Diagnostics |> List.filter (fun e -> e.FileName = filename) |> List.toArray
336+
let errors = Array.append parseRes.Errors tcErrors
337+
let scope = TypeCheckInfo(tcConfig, tcGlobals, ccuSigForFile, tcState.Ccu, tcImports, tcEnvAtEnd.AccessRights,
338+
projectFileName, filename, sink.GetResolutions(), sink.GetSymbolUses(), tcEnvAtEnd.NameEnv,
339+
loadClosure, reactorOps, checkAlive, textSnapshotInfo, implFile, sink.GetOpenDeclarations())
340+
FSharpCheckFileResults (filename, errors, Some scope, parseRes.DependencyFiles, None, reactorOps, true)
341+
342+
// parse files
343+
let parseScript (filename, source) = x.ParseScript(filename, source)
344+
let parseResults = Array.zip fileNames sources |> Array.map parseScript
345+
let parseHadErrors = parseResults |> Array.exists (fun p -> p.ParseHadErrors)
346+
let inputs = parseResults |> Array.choose (fun p -> p.ParseTree) |> Array.toList
347+
348+
// type check files
349+
let checkForErrors() = parseHadErrors
350+
let prefixPathOpt = None
351+
let tcSink = TcResultsSink.WithSink sink
352+
let tcOneInput = typeCheckOneInput (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt) tcSink
353+
let tcResults, tcState = (tcInitialState, inputs) ||> List.mapFold tcOneInput
354+
let (_tcEnvAtEnd, topAttrs, implFiles, _ccuSigsForFiles), tcState = TypeCheckMultipleInputsFinish(tcResults, tcState)
355+
let tcState, tcImplFiles = TypeCheckClosedInputSetFinish (implFiles, tcState)
356+
357+
let typeCheckResults = tcResults |> List.toArray |> Array.zip parseResults |> Array.map (makeTcResult tcState)
358+
359+
// make project results
360+
let parseErrors = parseResults |> Array.collect (fun p -> p.Errors)
361+
let tcErrors = errorScope.Diagnostics |> List.toArray
362+
let errors = Array.append parseErrors tcErrors
363+
let symbolUses = [sink.GetSymbolUses()]
364+
let projectResults = x.MakeProjectResults (projectFileName, parseResults, tcState, errors, symbolUses, Some topAttrs, Some tcImplFiles)
365+
366+
parseResults, typeCheckResults, projectResults
367+
368+
member x.ParseAndCheckProject_simple (projectFileName, fileNames: string[], sources: string[]) =
369+
use errorScope = new ErrorScope()
370+
371+
// parse files
372+
let parseScript (filename, source) = x.ParseScript(filename, source)
373+
let parseResults = Array.zip fileNames sources |> Array.map parseScript
374+
let parseHadErrors = parseResults |> Array.exists (fun p -> p.ParseHadErrors)
375+
let inputs = parseResults |> Array.choose (fun p -> p.ParseTree) |> Array.toList
376+
377+
// type check files
378+
let checkForErrors() = parseHadErrors
379+
let prefixPathOpt = None
380+
let tcState, topAttrs, tcImplFiles, _tcEnvAtEnd =
381+
TypeCheckClosedInputSet (ctok, checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcInitialState, inputs)
382+
383+
// make project results
384+
let parseErrors = parseResults |> Array.collect (fun p -> p.Errors)
385+
let tcErrors = errorScope.Diagnostics |> List.toArray
386+
let errors = Array.append parseErrors tcErrors
387+
let symbolUses = [] //todo:
388+
let projectResults = x.MakeProjectResults (projectFileName, parseResults, tcState, errors, symbolUses, Some topAttrs, Some tcImplFiles)
389+
390+
projectResults

fcs/fcs-fable/test/fcs-fable-test.fsproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
</ItemGroup>
1717

1818
<ItemGroup>
19-
<PackageReference Include="Fable.Core" Version="2.0.0-*" />
20-
<DotNetCliToolReference Include="dotnet-fable" Version="2.0.0-*" />
19+
<PackageReference Include="Fable.Core" Version="2.0.*" />
20+
<DotNetCliToolReference Include="dotnet-fable" Version="2.0.*" />
2121
</ItemGroup>
2222

2323
</Project>

src/fsharp/CompileOps.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5387,7 +5387,7 @@ type LoadClosure =
53875387
}
53885388

53895389
// cut-down version of TcConfig
5390-
type TcConfig (optimize: bool) =
5390+
type TcConfig (optimize: bool, defines: string list) =
53915391
#if TODO_REWORK_ASSEMBLY_LOAD
53925392
member x.primaryAssembly = PrimaryAssembly.DotNetCore
53935393
#else
@@ -5398,7 +5398,7 @@ type TcConfig (optimize: bool) =
53985398
member x.isInteractive = false
53995399
member x.mlCompatibility = false
54005400
member x.noDebugData = false
5401-
member x.conditionalCompilationDefines = []
5401+
member x.conditionalCompilationDefines = defines
54025402
member x.emitDebugInfoInQuotations = false
54035403
member x.errorSeverityOptions = FSharpErrorSeverityOptions.Default
54045404
member x.light = Some true

src/fsharp/service/service.fsi

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ open Microsoft.FSharp.Compiler.AbstractIL.IL
1515
open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library
1616
open Microsoft.FSharp.Compiler.AbstractIL.ILBinaryReader
1717
open Microsoft.FSharp.Compiler
18+
open Microsoft.FSharp.Compiler.AccessibilityLogic
1819
open Microsoft.FSharp.Compiler.Ast
1920
#if !FABLE_COMPILER
2021
open Microsoft.FSharp.Compiler.Driver
@@ -86,6 +87,25 @@ type public SemanticClassificationType =
8687
#if FABLE_COMPILER
8788
[<Sealed>]
8889
type internal TypeCheckInfo =
90+
internal new :
91+
tcConfig: TcConfig *
92+
tcGlobals: TcGlobals *
93+
ccuSigForFile: ModuleOrNamespaceType *
94+
thisCcu: CcuThunk *
95+
tcImports: TcImports *
96+
tcAccessRights: AccessorDomain *
97+
projectFileName: string *
98+
mainInputFileName: string *
99+
sResolutions: TcResolutions *
100+
sSymbolUses: TcSymbolUses *
101+
sFallback: NameResolutionEnv *
102+
loadClosure : LoadClosure option *
103+
reactorOps : IReactorOperations *
104+
checkAlive : (unit -> bool) *
105+
textSnapshotInfo: obj option *
106+
implFileOpt: TypedImplFile option *
107+
openDeclarations: OpenDeclaration[]
108+
-> TypeCheckInfo
89109
member ScopeResolutions: TcResolutions
90110
member ScopeSymbolUses: TcSymbolUses
91111
member TcGlobals: TcGlobals

0 commit comments

Comments
 (0)