F# Compiler Guide


There are several artifacts involved in the development of F#:

The FSharp.Compiler.Service is by far the largest of these components and contains nearly all logic that fsc and fsi use. It is the primary subject of this guide.

Key compiler data formats and representations

The following are the key data formats and internal data representations of the F# compiler code in its various configurations:

Key constructs and APIs for F# tooling

The following are the most relevant parts of the F# compiler tooling, making up the "engine" and API surface area of FSharp.Compiler.Service.

Key compiler phases

The following is a diagram of how the different phases of the F# compiler work:

    state "Compilation phases" as Flow {
      Lexing: Lexing
      Parsing: Parsing
      Import: Import
      Typechecking: Type checking
      Codegen: Code generation
      Emit: IL emit
      Inputs --> Lexing: Source and signature files
      Inputs --> Import: References
      Lexing --> Parsing
      Parsing --> Typechecking
      Import --> Typechecking
      Typechecking --> Codegen
      Codegen --> Emit
      state Lexing {
          BasicLexing: Basic Lexing
          WhitespaceSensitiveLexing: Whitespace Sensitive Lexing
          [*] --> BasicLexing
          BasicLexing --> WhitespaceSensitiveLexing: A token stream from input source text.
          WhitespaceSensitiveLexing --> [*]: A token stream, augmented per the F# Language Specification.
      state Parsing {
          Parser: Parsing
          [*] --> Parser
          Parser --> [*]: AST per the grammar in the F# Language Specification.
      state Import {
          Resolving: Resolving references
          ImportNET: Importing .NET references
          ImportFS: Importing F# references
          [*] --> Resolving
          Resolving --> ImportNET
          Resolving --> ImportFS
          ImportNET --> [*]
          ImportFS --> [*]
      state Typechecking {
          SequentialTypechecking: Sequentially type checking files
          PatternMatchCompilation: Pattern match compilation
          ConstraintSolving: Constraint solving
          PostInferenceChecks: Post inference checks
          [*] --> SequentialTypechecking
          SequentialTypechecking --> PatternMatchCompilation
          PatternMatchCompilation --> ConstraintSolving
          ConstraintSolving --> PostInferenceChecks
          PostInferenceChecks --> [*]
      state Codegen {
          QuotationTranslation: Quotation translation
          Optimization: Optimization
          Codegeneration: Code generation
          AbstractILRewrite: Abstract IL rewriting
          [*] --> QuotationTranslation
          QuotationTranslation --> Optimization
          Optimization --> Codegeneration
          Codegeneration --> AbstractILRewrite
          AbstractILRewrite --> [*]
      state Emit {
          Binary: Binary emit
          Reflection: Reflection emit
          Output: Output (assembly, references, PDBs, etc.)
          [*] --> Binary
          [*] --> Reflection
          Binary --> Output
          Reflection --> Output

The following are the key phases and high-level logical operations of the F# compiler code in its various configurations:

These and transformations used to build the following:


The F# compiler is bootstrapped. That is, an existing F# compiler is used to build a "proto" compiler from the current source code. That "proto" compiler is then used to compile itself, producing a "final" compiler. This ensures the final compiler is compiled with all relevant optimizations and fixes.


FSharp.Build.dll and Microsoft.FSharp.targets give MSBuild support for F# projects (.fsproj) and contain the targets. Although not strictly part of the F# compiler, they are essential for using F# in all contexts for .NET, aside from some more targeted scripting scenarios. The targets expose things like the CoreCompile and Fsc tasks called by MSBuild.