Last active
April 29, 2022 09:12
-
-
Save Happypig375/db80980bbfa5715ebf7ebcb41e472643 to your computer and use it in GitHub Desktop.
Type switching in F#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[SharpLab.Runtime.JitGeneric(typeof(int))] | |
[SharpLab.Runtime.JitGeneric(typeof(long))] | |
[SharpLab.Runtime.JitGeneric(typeof(byte))] | |
void f<T>(T x) { | |
if (typeof(T) == typeof(bool)) System.Console.WriteLine((bool)(object)x); | |
else if (typeof(T) == typeof(int)) System.Console.WriteLine((int)(object)x); | |
else if (typeof(T) == typeof(long)) System.Console.WriteLine((long)(object)x); | |
} | |
[SharpLab.Runtime.JitGeneric(typeof(int))] | |
[SharpLab.Runtime.JitGeneric(typeof(long))] | |
[SharpLab.Runtime.JitGeneric(typeof(byte))] | |
T g<T>(T x) { | |
if (typeof(T) == typeof(int)) return (T)(object)((int)(object)x + 1); | |
else if (typeof(T) == typeof(long)) return (T)(object)((long)(object)x + 1L); | |
else throw null; | |
} | |
/* | |
; Core CLR 6.0.322.12309 on x86 | |
<Program>$.<Main>$(System.String[]) | |
L0000: ret | |
<Program>$.<<Main>$>g__f|0_0[[System.Int32, System.Private.CoreLib]](Int32) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: call System.Console.WriteLine(Int32) | |
L0008: pop ebp | |
L0009: ret | |
<Program>$.<<Main>$>g__f|0_0[[System.Int64, System.Private.CoreLib]](Int64) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: push dword ptr [ebp+0xc] | |
L0006: push dword ptr [ebp+8] | |
L0009: call System.Console.WriteLine(Int64) | |
L000e: pop ebp | |
L000f: ret 8 | |
<Program>$.<<Main>$>g__f|0_0[[System.Byte, System.Private.CoreLib]](Byte) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: pop ebp | |
L0004: ret | |
<Program>$.<<Main>$>g__g|0_1[[System.Int32, System.Private.CoreLib]](Int32) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: lea eax, [ecx+1] | |
L0006: pop ebp | |
L0007: ret | |
<Program>$.<<Main>$>g__g|0_1[[System.Int64, System.Private.CoreLib]](Int64) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: mov eax, [ebp+8] | |
L0006: mov edx, [ebp+0xc] | |
L0009: add eax, 1 | |
L000c: adc edx, 0 | |
L000f: pop ebp | |
L0010: ret 8 | |
<Program>$.<<Main>$>g__g|0_1[[System.Byte, System.Private.CoreLib]](Byte) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: xor ecx, ecx | |
L0005: call 0x727a19f0 | |
L000a: int3 | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let inline typeBranch (x: 'T) ([<InlineIfLambda>] thenBranch : 'U -> 'V) ([<InlineIfLambda>] elseBranch : unit -> 'W) = | |
if System.Type.(=)(typeof<'T>, typeof<'U>) then | |
x |> box |> LanguagePrimitives.IntrinsicFunctions.UnboxFast<'U> | |
|> thenBranch |> box |> LanguagePrimitives.IntrinsicFunctions.UnboxFast<'W> | |
else elseBranch() | |
[<SharpLab.Runtime.JitGeneric(typeof<int>)>] | |
[<SharpLab.Runtime.JitGeneric(typeof<int64>)>] | |
[<SharpLab.Runtime.JitGeneric(typeof<byte>)>] | |
let f (x: 'T): unit = | |
typeBranch x (System.Console.WriteLine : bool -> unit) <| fun () -> | |
typeBranch x (System.Console.WriteLine : int -> unit) <| fun () -> | |
typeBranch x (System.Console.WriteLine : int64 -> unit) <| fun () -> | |
() | |
[<SharpLab.Runtime.JitGeneric(typeof<int>)>] | |
[<SharpLab.Runtime.JitGeneric(typeof<int64>)>] | |
[<SharpLab.Runtime.JitGeneric(typeof<byte>)>] | |
let g (x: 'T): 'T = | |
typeBranch x ((+) 1) <| fun () -> | |
typeBranch x ((+) 1L) <| fun () -> | |
raise null | |
(* | |
; Core CLR 6.0.322.12309 on x86 | |
_.typeBranch(!!0, Microsoft.FSharp.Core.FSharpFunc`2<!!1,!!2>, Microsoft.FSharp.Core.FSharpFunc`2<Microsoft.FSharp.Core.Unit,!!3>) | |
; Open generics cannot be JIT-compiled. | |
; However you can use attribute SharpLab.Runtime.JitGeneric to specify argument types. | |
; Example: [JitGeneric(typeof(int)), JitGeneric(typeof(string))] void M<T>() { ... }. | |
_.f[[System.Int32, System.Private.CoreLib]](Int32) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: call System.Console.WriteLine(Int32) | |
L0008: pop ebp | |
L0009: ret | |
_.f[[System.Int64, System.Private.CoreLib]](Int64) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: push dword ptr [ebp+0xc] | |
L0006: push dword ptr [ebp+8] | |
L0009: call System.Console.WriteLine(Int64) | |
L000e: pop ebp | |
L000f: ret 8 | |
_.f[[System.Byte, System.Private.CoreLib]](Byte) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: pop ebp | |
L0004: ret | |
_.g[[System.Int32, System.Private.CoreLib]](Int32) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: lea eax, [ecx+1] | |
L0006: pop ebp | |
L0007: ret | |
_.g[[System.Int64, System.Private.CoreLib]](Int64) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: mov eax, [ebp+8] | |
L0006: mov edx, [ebp+0xc] | |
L0009: add eax, 1 | |
L000c: adc edx, 0 | |
L000f: pop ebp | |
L0010: ret 8 | |
_.g[[System.Byte, System.Private.CoreLib]](Byte) | |
L0000: push ebp | |
L0001: mov ebp, esp | |
L0003: xor ecx, ecx | |
L0005: call 0x727a19f0 | |
L000a: int3 | |
*) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment