forked from dotnet/fsharp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCompilerGlobalState.fs
78 lines (59 loc) · 3.62 KB
/
CompilerGlobalState.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
/// Defines the global environment for all type checking.
module FSharp.Compiler.CompilerGlobalState
open System
open System.Collections.Concurrent
open System.Threading
open FSharp.Compiler.Syntax.PrettyNaming
open FSharp.Compiler.Text
/// Generates compiler-generated names. Each name generated also includes the StartLine number of the range passed in
/// at the point of first generation.
///
/// This type may be accessed concurrently, though in practice it is only used from the compilation thread.
/// It is made concurrency-safe since a global instance of the type is allocated in tast.fs, and it is good
/// policy to make all globally-allocated objects concurrency safe in case future versions of the compiler
/// are used to host multiple concurrent instances of compilation.
type NiceNameGenerator() =
let basicNameCounts = ConcurrentDictionary<string, int ref>(max Environment.ProcessorCount 1, 127)
// Cache this as a delegate.
let basicNameCountsAddDelegate = Func<string, int ref>(fun _ -> ref 0)
member _.FreshCompilerGeneratedNameOfBasicName (basicName, m: range) =
let countCell = basicNameCounts.GetOrAdd(basicName, basicNameCountsAddDelegate)
let count = Interlocked.Increment(countCell)
CompilerGeneratedNameSuffix basicName (string m.StartLine + (match (count-1) with 0 -> "" | n -> "-" + string n))
member this.FreshCompilerGeneratedName (name, m: range) =
this.FreshCompilerGeneratedNameOfBasicName (GetBasicNameOfPossibleCompilerGeneratedName name, m)
/// Generates compiler-generated names marked up with a source code location, but if given the same unique value then
/// return precisely the same name. Each name generated also includes the StartLine number of the range passed in
/// at the point of first generation.
///
/// This type may be accessed concurrently, though in practice it is only used from the compilation thread.
/// It is made concurrency-safe since a global instance of the type is allocated in tast.fs.
type StableNiceNameGenerator() =
let niceNames = ConcurrentDictionary<string * int64, string>(max Environment.ProcessorCount 1, 127)
let innerGenerator = new NiceNameGenerator()
member x.GetUniqueCompilerGeneratedName (name, m: range, uniq) =
let basicName = GetBasicNameOfPossibleCompilerGeneratedName name
let key = basicName, uniq
niceNames.GetOrAdd(key, fun (basicName, _) -> innerGenerator.FreshCompilerGeneratedNameOfBasicName(basicName, m))
type internal CompilerGlobalState () =
/// A global generator of compiler generated names
let globalNng = NiceNameGenerator()
/// A global generator of stable compiler generated names
let globalStableNameGenerator = StableNiceNameGenerator ()
/// A name generator used by IlxGen for static fields, some generated arguments and other things.
let ilxgenGlobalNng = NiceNameGenerator ()
member _.NiceNameGenerator = globalNng
member _.StableNameGenerator = globalStableNameGenerator
member _.IlxGenNiceNameGenerator = ilxgenGlobalNng
/// Unique name generator for stamps attached to lambdas and object expressions
type Unique = int64
//++GLOBAL MUTABLE STATE (concurrency-safe)
let mutable private uniqueCount = 0L
let newUnique() = System.Threading.Interlocked.Increment &uniqueCount
/// Unique name generator for stamps attached to to val_specs, tycon_specs etc.
//++GLOBAL MUTABLE STATE (concurrency-safe)
let mutable stampCount = 0L
let newStamp() =
let stamp = System.Threading.Interlocked.Increment &stampCount
stamp