|
| 1 | +--- |
| 2 | +title: Representations |
| 3 | +category: Compiler Internals |
| 4 | +categoryindex: 200 |
| 5 | +index: 350 |
| 6 | +--- |
| 7 | +# Representation Decisions in the F# Compiler |
| 8 | + |
| 9 | +Consider the following declarations, all of which look very similar. |
| 10 | + |
| 11 | +```fsharp |
| 12 | +module M = |
| 13 | + let z = 1 |
| 14 | + let f = x + z |
| 15 | + |
| 16 | +
|
| 17 | +type C(w: int, z: int) = |
| 18 | + |
| 19 | + let f x = x + z |
| 20 | + let f x = f 3 + x |
| 21 | + |
| 22 | +
|
| 23 | +let g (z: int) = |
| 24 | + let f x = x + 1 |
| 25 | +``` |
| 26 | +Part of the job of the F# compiler is to "decide" how these declarations are compiled. The following acts as a guide to how these different bindings are represented and where these decisions are made. |
| 27 | + |
| 28 | +First for module-level `let` bindings. These representations are decided by code in `CheckExpressions.fs` and `CheckDeclarations.fs` based on syntax. |
| 29 | + |
| 30 | +```fsharp |
| 31 | +module M = |
| 32 | + let z = 1 // z --> static property + field, required by spec, compiled name mandated |
| 33 | + let f x = x + z // f --> static method, required by spec, compiled name mandated |
| 34 | +``` |
| 35 | + |
| 36 | +Next for class-level `let` bindings. These representations are decided by code in `CheckIncrementalClasses.fs` based on analysis of use. |
| 37 | +```fsharp |
| 38 | +// Decided in CheckIncrementalClasses.fs based on analysis of use |
| 39 | +type C(w: int, z: int) = // w --> local to object constructor, required by spec |
| 40 | + // z --> private instance field, required by spec |
| 41 | + let f x = x + z // f --> private instance method, required by spec, compiled name not mandated |
| 42 | + // Note: initially uses an ephemeral 'f' Val then creates a member Val with compiled name |
| 43 | + |
| 44 | + let f x = f 3 + x // f --> private instance method, required by spec, compiled name not mandated |
| 45 | + // Note: initially uses an ephemeral 'f' Val then creates a member Val with compiled name |
| 46 | + |
| 47 | + static let g x = x + 1 // g --> private static method, required by spec, compiled name not mandated, initially uses an ephemeral 'g' Val then creates a member Val with compiled name |
| 48 | + |
| 49 | + static let g x = g 3 // g --> private static method, required by spec, compiled name not mandated, initially uses an ephemeral 'g' Val then creates a member Val with compiled name |
| 50 | +``` |
| 51 | +Next for expression-level `let` bindings. These representations are decided by code in various optimization phases. |
| 52 | +```fsharp |
| 53 | +let g (z: int) = // z --> local + field in closure for 'f', not mandated |
| 54 | + let f x = x + 1 // f --> FSharpFunc value, or maybe a static method, not mandated |
| 55 | + // Decided in various optimization phases |
| 56 | +``` |
| 57 | + |
| 58 | +> NOTE: The representation decision is implied by the addition of ValReprInfo to the `Val` node. |
0 commit comments