From f45ef819b5310de521645dbc68ccbfc57f8edda4 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Mon, 19 Jul 2021 10:55:52 +0100 Subject: [PATCH] [RFC FS-1087, FS-1097, FS-1098] tasks, resumable state machines, inline on parameters (#6811) * Move existing Compiler.ComponentTests to a new Compiler.fs framework (#9839) (#9847) * Move existing Compiler.ComponentTests to a new Compiler.fs framework; Add 'parse' function * Changed some wording in error messages Co-authored-by: Vlad Zarytovskii * fix build * fix order of diagnostics * update baselines * Delete FSharp.Compiler.Service.fsproj * fix comments * fix comments * fix build * fix build * Reduce number of typeEquiv checks (#10324) (#10374) Co-authored-by: Steffen Forkmann * xlf * fix build * fix build * fix build * fix build * fix list and array builder perf * better perf testing * better perf testing * better perf testing * update baselines * work on taskSeq { ... } * remove old file * enable all benchmarks * update benchmarks * update baseline * static checking of resumable code * static checking of resumable code * fix build * fix build * fix build * fix build * fix build * fix build * fix baseline * try fix stack overflow * fix up tests * add some negative testing, simplify implementation * fix up tests * fix baseline * fix test and add negative baselines * rename intrinsic and add test for seq case * fix build * fix and rename test * fix test * improve debugging * improve debugging of try/with and try/finally * fix baseline * infer resumable code from single attribute on delegate type * update samples * inline if lambda * update baselines * fix check * delegate and computed function reductions for inlined code * update baselines * update baselines * update test * fix test that failed randomly due to inexact floating point * add tests for generated IL * update tests * don't use InlineIfLambda on sumBy and averageBy due to slight floating point changes * add ability for struct machines to implement additional interfaces (needed for low allocation co-routines) * add coroutines * update baselines * resumable code combinators and tailcalls for coroutines * fix baselinhe * make tasks using shared resumable code combinators the default. Also testing and fixes for dynamic execution of resumable code * update baselines * suppress warning in FSharp.Core * suppress warning in FSharp.Core * fix build * fix build * fix build * update test * only struct state machines * codegen IResumableStateMachine * update baselines * update baselines * notes on sample * fix build * Update coroutine.fs * Negative testing following spec for compilability. Additional testing for dynamic implementation of tasks * simpler coroutine sample, fix build * update baselines * remove unused state vars from internal represenation of object expressions * add coroutine example * update perf benchmarks * remove old files * code cleanup * add compilergenerated attribute, add async2 approximate implementation * test async perf w.r.t. previous compiler, add test for reduced stack trace * using on IAsyncDisposable * remove dynamic Awaiter field from tasks * update surface area * add backgroundTask { ... } * surface area test only for decalred members etc. * fix test * add dynamic tests for backgroundTask * fix codegen bug * fix build * simplify SRTP use in task.fs/fsi * fix build and baselines * fix build * fix build * fix build * fix pacakge * remove RFC FS-1099 from this PR * remove RFC FS-1099 from this PR * backgroundTask only switches to background if necessary * Update tasks.fs * fix test * clear sync context for test * clear sync context for test * update baseline * code review * fix build * fix build * fix clearing state machines * fix to clearing code * improve generated task code and debugging * only update baselines on failure * fix some cases of debug stepping, improve isnull codegen, add more tests * move TaskPerf to benchmarks directory * fix baseline * only update baselines when things changed * fix baselines * update baselines * fix baselines * fix build * fix some tests, add hard error on language version check * reset unchanged files * update baselines * update baselines * fix baseline * fix comparer * flags * Revert "flags" This reverts commit 5b2a0118311150cea9be567d497a917fde0b92f5. * fix merge * fix build * fix build * fix build * update baseline * fix build * fix build * update baseline * fix baselines * update baseline * fix build * fix build * update baseline * fix test * code review changes Co-authored-by: Kevin Ransom (msft) Co-authored-by: Phillip Carter Co-authored-by: dotnet bot Co-authored-by: Vlad Zarytovskii Co-authored-by: Don Syme Co-authored-by: Steffen Forkmann Co-authored-by: Brett V. Forsgren --- .../TaskPerf.Benchmarks-report-github.md | 67 + FSharp.sln | 95 +- FSharpBuild.Directory.Build.props | 9 + VisualFSharp.sln | 30 + src/fsharp/CheckComputationExpressions.fs | 45 +- src/fsharp/CheckDeclarations.fs | 13 +- src/fsharp/CheckExpressions.fs | 147 +- src/fsharp/CheckExpressions.fsi | 3 + src/fsharp/CompilerDiagnostics.fs | 3 +- src/fsharp/DetupleArgs.fs | 4 +- src/fsharp/FSComp.txt | 25 +- .../FSharp.Compiler.Service.fsproj | 8 +- .../FSharp.Compiler.Service/StandardError.txt | 0 .../StandardOutput.txt | 1 + src/fsharp/FSharp.Core/FSharp.Core.fsproj | 34 +- src/fsharp/FSharp.Core/FSharp.Core.nuspec | 8 + src/fsharp/FSharp.Core/array.fs | 8 +- .../FSharp.Core/fslib-extra-pervasives.fs | 5 + src/fsharp/FSharp.Core/prim-types.fs | 7 +- src/fsharp/FSharp.Core/prim-types.fsi | 18 +- src/fsharp/FSharp.Core/resumable.fs | 375 ++++ src/fsharp/FSharp.Core/resumable.fsi | 204 ++ src/fsharp/FSharp.Core/seqcore.fs | 1 + src/fsharp/FSharp.Core/seqcore.fsi | 8 +- src/fsharp/FSharp.Core/tasks.fs | 384 ++++ src/fsharp/FSharp.Core/tasks.fsi | 311 +++ src/fsharp/FindUnsolved.fs | 2 +- src/fsharp/IlxGen.fs | 681 +++++-- src/fsharp/InnerLambdasToTopLevelFuncs.fs | 12 +- src/fsharp/LanguageFeatures.fs | 3 + src/fsharp/LanguageFeatures.fsi | 1 + src/fsharp/LowerCallsAndSeqs.fs | 101 +- src/fsharp/LowerCallsAndSeqs.fsi | 2 +- src/fsharp/LowerStateMachines.fs | 906 +++++++++ src/fsharp/LowerStateMachines.fsi | 37 + src/fsharp/Optimizer.fs | 284 ++- src/fsharp/PatternMatchCompilation.fs | 8 +- src/fsharp/PostInferenceChecks.fs | 209 +- src/fsharp/PrettyNaming.fs | 6 + src/fsharp/PrettyNaming.fsi | 13 + src/fsharp/QuotationTranslator.fs | 7 +- src/fsharp/SignatureConformance.fs | 9 + src/fsharp/SyntaxTree.fs | 51 +- src/fsharp/SyntaxTree.fsi | 60 +- src/fsharp/SyntaxTreeOps.fs | 7 +- src/fsharp/SyntaxTreeOps.fsi | 5 - src/fsharp/TcGlobals.fs | 46 +- src/fsharp/TypedTree.fs | 65 +- src/fsharp/TypedTreeOps.fs | 339 +++- src/fsharp/TypedTreeOps.fsi | 58 +- src/fsharp/TypedTreePickle.fs | 39 +- src/fsharp/fsi/fsi.fs | 2 +- src/fsharp/lib.fs | 18 + src/fsharp/lib.fsi | 18 + src/fsharp/pars.fsy | 10 +- src/fsharp/range.fs | 60 +- src/fsharp/range.fsi | 16 + src/fsharp/service/FSharpParseFileResults.fs | 8 +- src/fsharp/symbols/Exprs.fs | 2 +- src/fsharp/symbols/Symbols.fs | 2 - src/fsharp/symbols/Symbols.fsi | 5 +- src/fsharp/xlf/FSComp.txt.cs.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.de.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.es.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.fr.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.it.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.ja.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.ko.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.pl.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.pt-BR.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.ru.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.tr.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.zh-Hans.xlf | 115 ++ src/fsharp/xlf/FSComp.txt.zh-Hant.xlf | 115 ++ .../EmittedIL/TailCalls.fs | 102 +- ...erService.SurfaceArea.netstandard.expected | 122 +- .../FSharp.Core.UnitTests.fsproj | 4 +- .../FSharp.Core/CreateComparersRegression.fsx | 2 +- .../ArrayModule2.fs | 2 +- .../Microsoft.FSharp.Control/Tasks.fs | 1325 ++++++++++++ .../Microsoft.FSharp.Control/TasksDynamic.fs | 1399 +++++++++++++ tests/FSharp.Core.UnitTests/LibraryTestFx.fs | 8 +- tests/FSharp.Core.UnitTests/SurfaceArea.fs | 1039 +++------- tests/FSharp.Test.Utilities/CompilerAssert.fs | 18 +- tests/FSharp.Test.Utilities/ILChecker.fs | 32 +- tests/benchmarks/TaskPerf/TaskBuilder.fs | 416 ++++ tests/benchmarks/TaskPerf/TaskPerf.fs | 476 +++++ tests/benchmarks/TaskPerf/TaskPerf.fsproj | 44 + tests/benchmarks/TaskPerf/array.fs | 192 ++ tests/benchmarks/TaskPerf/async2.fs | 1131 +++++++++++ tests/benchmarks/TaskPerf/async2.fsi | 255 +++ tests/benchmarks/TaskPerf/coroutine.fs | 279 +++ tests/benchmarks/TaskPerf/coroutineBasic.fs | 169 ++ tests/benchmarks/TaskPerf/empty.fs | 5 + tests/benchmarks/TaskPerf/list.fs | 195 ++ tests/benchmarks/TaskPerf/option.fs | 310 +++ tests/benchmarks/TaskPerf/option2.fs | 25 + tests/benchmarks/TaskPerf/seq2.fs | 262 +++ tests/benchmarks/TaskPerf/sync.fs | 88 + tests/benchmarks/TaskPerf/taskSeq.fs | 599 ++++++ .../TaskPerfCSharp/TaskPerfCSharp.cs | 125 ++ .../TaskPerfCSharp/TaskPerfCSharp.csproj | 14 + .../TaskPerfPreviousCompiler.fsproj | 30 + .../TaskPerfPreviousCompiler/defs.fs | 14 + .../ComputationExpressionOptimizations.fs | 317 +++ .../EmittedIL/ComputedListExpressions.fs | 296 ++- .../EmittedIL/DelegateAndFuncOptimizations.fs | 530 +++++ .../CodeGen/EmittedIL/StaticMember.fs | 40 +- .../CodeGen/EmittedIL/TaskGeneratedCode.fs | 1141 +++++++++++ .../Compiler/Language/OptionalInteropTests.fs | 2 +- .../Language/SpanOptimizationTests.fs | 99 +- tests/fsharp/FSharpSuite.Tests.fsproj | 5 +- tests/fsharp/core/seq/test.fsx | 28 +- .../core/state-machines/neg-resumable-01.bsl | 18 + .../core/state-machines/neg-resumable-01.fsx | 152 ++ .../core/state-machines/neg-resumable-02.bsl | 6 + .../core/state-machines/neg-resumable-02.fsx | 79 + tests/fsharp/core/state-machines/test.fsx | 672 +++++++ tests/fsharp/tests.fs | 39 + .../CCtorDUWithMember01.il.bsl | 40 +- .../CCtorDUWithMember02.il.bsl | 22 +- .../CCtorDUWithMember03.il.bsl | 22 +- .../CCtorDUWithMember04.il.bsl | 22 +- .../GeneratedIterators/GenIter01.il.bsl | 28 +- .../GeneratedIterators/GenIter02.il.bsl | 28 +- .../GeneratedIterators/GenIter03.il.bsl | 28 +- .../GeneratedIterators/GenIter04.il.bsl | 34 +- .../ListExpressionSteppingTest6.il.bsl | 98 +- .../CodeGen/EmittedIL/Misc/ForLoop01.il.bsl | 38 +- .../CodeGen/EmittedIL/Misc/ForLoop02.il.bsl | 40 +- .../CodeGen/EmittedIL/Misc/ForLoop03.il.bsl | 65 +- .../CodeGen/EmittedIL/Misc/Lock01.il.bsl | 33 +- .../EmittedIL/Misc/NoBoxingOnDispose01.il.bsl | 29 +- .../Misc/TryWith_NoFilterBlocks01.il.bsl | 49 +- .../Linq101Aggregates01.il.bsl | 1792 ++++++++--------- .../Linq101ElementOperators01.il.bsl | 180 +- .../Linq101Grouping01.il.bsl | 2 +- .../Linq101Joins01.il.bsl | 4 +- .../Linq101Ordering01.il.bsl | 180 +- .../Linq101Partitioning01.il.bsl | 180 +- .../Linq101Quantifiers01.il.bsl | 92 +- .../Linq101Select01.il.bsl | 268 +-- .../Linq101SetOperators01.il.bsl | 176 +- .../Linq101Where01.il.bsl | 48 +- .../SeqExpressionSteppingTest5.il.bsl | 48 +- .../SeqExpressionSteppingTest6.il.bsl | 48 +- .../SeqExpressionSteppingTest7.il.bsl | 70 +- .../SeqExpressionTailCalls01.il.bsl | 5 +- .../SeqExpressionTailCalls02.il.bsl | 6 +- .../EmittedIL/StaticInit/LetBinding01.il.bsl | 21 +- .../TestFunctions/TestFunction3b.il.bsl | 55 +- .../TestFunctions/TestFunction3c.il.bsl | 81 +- .../TestFunctions/Testfunction22h.il.bsl | 27 +- .../TestFunctions/Testfunction3.il.bsl | 23 +- .../TestFunctions/Testfunction4.il.bsl | 17 +- .../EmittedIL/Tuples/TupleElimination.il.bsl | 130 +- tests/fsharpqa/Source/KnownFail.txt | 2 +- .../Source/Optimizations/CompareIL.cmd | 4 +- .../ForLoop/ForEachOnArray01.il.bsl | 14 +- .../ForLoop/ForEachOnList01.il.bsl | 4 +- .../ForLoop/ForEachOnString01.il.bsl | 4 +- .../ForLoop/NoAllocationOfTuple01.il.bsl | 14 +- .../ForLoop/NoIEnumerable01.il.bsl | 10 +- .../ForLoop/NoIEnumerable02.il.bsl | 10 +- .../ForLoop/NoIEnumerable03.il.bsl | 8 +- .../ForLoop/ZeroToArrLength01.il.bsl | 14 +- .../ForLoop/ZeroToArrLength02.il.bsl | 25 +- .../GenericComparison/Compare01.il.bsl | 14 +- .../GenericComparison/Compare02.il.bsl | 12 +- .../GenericComparison/Compare03.il.bsl | 8 +- .../GenericComparison/Compare04.il.bsl | 8 +- .../GenericComparison/Compare05.il.bsl | 14 +- .../GenericComparison/Compare06.il.bsl | 14 +- .../GenericComparison/Compare07.il.bsl | 14 +- .../GenericComparison/Compare08.il.bsl | 14 +- .../GenericComparison/Compare09.il.bsl | 14 +- .../GenericComparison/Compare10.il.bsl | 14 +- .../GenericComparison/Compare11.il.bsl | 14 +- .../GenericComparison/Equals01.il.bsl | 12 +- .../GenericComparison/Equals02.il.bsl | 8 +- .../GenericComparison/Equals03.il.bsl | 8 +- .../GenericComparison/Equals04.il.bsl | 14 +- .../GenericComparison/Equals05.il.bsl | 14 +- .../GenericComparison/Equals06.il.bsl | 14 +- .../GenericComparison/Equals07.il.bsl | 14 +- .../GenericComparison/Equals08.il.bsl | 14 +- .../GenericComparison/Equals09.il.bsl | 14 +- .../GenericComparison/Hash01.il.bsl | 12 +- .../GenericComparison/Hash02.il.bsl | 14 +- .../GenericComparison/Hash03.il.bsl | 8 +- .../GenericComparison/Hash04.il.bsl | 8 +- .../GenericComparison/Hash05.il.bsl | 14 +- .../GenericComparison/Hash06.il.bsl | 14 +- .../GenericComparison/Hash07.il.bsl | 12 +- .../GenericComparison/Hash08.il.bsl | 14 +- .../GenericComparison/Hash09.il.bsl | 14 +- .../GenericComparison/Hash10.il.bsl | 12 +- .../GenericComparison/Hash11.il.bsl | 12 +- .../GenericComparison/Hash12.il.bsl | 14 +- .../Optimizations/Inlining/Match01.il.bsl | 12 +- .../Optimizations/Inlining/Match02.il.bsl | 12 +- .../Inlining/StructUnion01.il.bsl | 4 +- .../TheBigFileOfDebugStepping.fsx | 289 ++- 203 files changed, 19043 insertions(+), 4318 deletions(-) create mode 100644 BenchmarkDotNet.Artifacts/results/TaskPerf.Benchmarks-report-github.md create mode 100644 src/fsharp/FSharp.Compiler.Service/StandardError.txt create mode 100644 src/fsharp/FSharp.Compiler.Service/StandardOutput.txt create mode 100644 src/fsharp/FSharp.Core/resumable.fs create mode 100644 src/fsharp/FSharp.Core/resumable.fsi create mode 100644 src/fsharp/FSharp.Core/tasks.fs create mode 100644 src/fsharp/FSharp.Core/tasks.fsi create mode 100644 src/fsharp/LowerStateMachines.fs create mode 100644 src/fsharp/LowerStateMachines.fsi create mode 100644 tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Tasks.fs create mode 100644 tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/TasksDynamic.fs create mode 100644 tests/benchmarks/TaskPerf/TaskBuilder.fs create mode 100644 tests/benchmarks/TaskPerf/TaskPerf.fs create mode 100644 tests/benchmarks/TaskPerf/TaskPerf.fsproj create mode 100644 tests/benchmarks/TaskPerf/array.fs create mode 100644 tests/benchmarks/TaskPerf/async2.fs create mode 100644 tests/benchmarks/TaskPerf/async2.fsi create mode 100644 tests/benchmarks/TaskPerf/coroutine.fs create mode 100644 tests/benchmarks/TaskPerf/coroutineBasic.fs create mode 100644 tests/benchmarks/TaskPerf/empty.fs create mode 100644 tests/benchmarks/TaskPerf/list.fs create mode 100644 tests/benchmarks/TaskPerf/option.fs create mode 100644 tests/benchmarks/TaskPerf/option2.fs create mode 100644 tests/benchmarks/TaskPerf/seq2.fs create mode 100644 tests/benchmarks/TaskPerf/sync.fs create mode 100644 tests/benchmarks/TaskPerf/taskSeq.fs create mode 100644 tests/benchmarks/TaskPerfCSharp/TaskPerfCSharp.cs create mode 100644 tests/benchmarks/TaskPerfCSharp/TaskPerfCSharp.csproj create mode 100644 tests/benchmarks/TaskPerfPreviousCompiler/TaskPerfPreviousCompiler.fsproj create mode 100644 tests/benchmarks/TaskPerfPreviousCompiler/defs.fs create mode 100644 tests/fsharp/Compiler/CodeGen/EmittedIL/ComputationExpressionOptimizations.fs create mode 100644 tests/fsharp/Compiler/CodeGen/EmittedIL/DelegateAndFuncOptimizations.fs create mode 100644 tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs create mode 100644 tests/fsharp/core/state-machines/neg-resumable-01.bsl create mode 100644 tests/fsharp/core/state-machines/neg-resumable-01.fsx create mode 100644 tests/fsharp/core/state-machines/neg-resumable-02.bsl create mode 100644 tests/fsharp/core/state-machines/neg-resumable-02.fsx create mode 100644 tests/fsharp/core/state-machines/test.fsx diff --git a/BenchmarkDotNet.Artifacts/results/TaskPerf.Benchmarks-report-github.md b/BenchmarkDotNet.Artifacts/results/TaskPerf.Benchmarks-report-github.md new file mode 100644 index 00000000000..6cce7d6b240 --- /dev/null +++ b/BenchmarkDotNet.Artifacts/results/TaskPerf.Benchmarks-report-github.md @@ -0,0 +1,67 @@ +``` ini + +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +Intel Xeon CPU E5-1620 0 3.60GHz, 1 CPU, 8 logical and 4 physical cores +.NET Core SDK=5.0.104 + [Host] : .NET Core 5.0.6 (CoreCLR 5.0.621.22011, CoreFX 5.0.621.22011), X64 RyuJIT DEBUG + DefaultJob : .NET Core 5.0.6 (CoreCLR 5.0.621.22011, CoreFX 5.0.621.22011), X64 RyuJIT + + +``` +| Method | Categories | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|-------------------------------------------- |----------------------- |---------------:|--------------:|--------------:|---------------:|-------:|--------:|-----------:|--------:|------:|------------:| +| ManyWriteFile_CSharpTasks | ManyWriteFile | 4,186.6 μs | 81.32 μs | 201.00 μs | 4,187.4 μs | 1.00 | 0.00 | 15.6250 | - | - | 117288 B | +| ManyWriteFile_taskBuilder | ManyWriteFile | 5,744.5 μs | 124.34 μs | 356.76 μs | 5,712.3 μs | 1.38 | 0.11 | 62.5000 | - | - | 444882 B | +| ManyWriteFile_async | ManyWriteFile | 6,108.8 μs | 121.27 μs | 271.23 μs | 6,132.1 μs | 1.46 | 0.10 | 132.8125 | - | - | 704991 B | +| ManyWriteFile_task | ManyWriteFile | 5,014.3 μs | 100.18 μs | 204.65 μs | 4,973.0 μs | 1.19 | 0.07 | 15.6250 | - | - | 116996 B | +| ManyWriteFile_async2 | ManyWriteFile | 5,358.4 μs | 106.05 μs | 211.79 μs | 5,374.1 μs | 1.27 | 0.07 | 15.6250 | - | - | 117140 B | +| | | | | | | | | | | | | +| NonAsyncBinds_CSharpTasks | NonAsyncBinds | 17,444.8 μs | 374.32 μs | 1,097.80 μs | 17,030.4 μs | 1.00 | 0.00 | 15125.0000 | - | - | 79200000 B | +| NonAsyncBinds_taskBuilder | NonAsyncBinds | 26,000.1 μs | 440.68 μs | 880.09 μs | 25,621.3 μs | 1.47 | 0.09 | 22187.5000 | - | - | 116000000 B | +| NonAsyncBinds_async | NonAsyncBinds | 1,303,920.2 μs | 63,453.67 μs | 177,930.90 μs | 1,269,891.9 μs | 74.52 | 10.59 | 52000.0000 | - | - | 276000000 B | +| NonAsyncBinds_async2 | NonAsyncBinds | 24,213.0 μs | 191.23 μs | 178.88 μs | 24,168.6 μs | 1.38 | 0.09 | 18812.5000 | 62.5000 | - | 98400000 B | +| NonAsyncBinds_task | NonAsyncBinds | 16,693.5 μs | 302.84 μs | 759.75 μs | 16,586.1 μs | 0.95 | 0.07 | 15125.0000 | - | - | 79200000 B | +| | | | | | | | | | | | | +| AsyncBinds_CSharpTasks | AsyncBinds | 8,335.4 μs | 190.47 μs | 558.61 μs | 8,197.5 μs | 1.00 | 0.00 | 15.6250 | - | - | 112119 B | +| AsyncBinds_taskBuilder | AsyncBinds | 11,567.6 μs | 229.28 μs | 522.18 μs | 11,360.0 μs | 1.39 | 0.12 | 296.8750 | - | - | 1559252 B | +| AsyncBinds_async | AsyncBinds | 127,872.2 μs | 3,090.27 μs | 8,866.56 μs | 127,900.8 μs | 15.38 | 1.47 | 1333.3333 | - | - | 8312000 B | +| AsyncBinds_task | AsyncBinds | 9,897.9 μs | 314.55 μs | 927.46 μs | 10,058.4 μs | 1.19 | 0.15 | 31.2500 | - | - | 192096 B | +| AsyncBinds_async2 | AsyncBinds | 8,165.2 μs | 156.64 μs | 347.09 μs | 8,051.9 μs | 0.98 | 0.07 | 62.5000 | - | - | 352218 B | +| | | | | | | | | | | | | +| SingleSyncTask_CSharpTasks | SingleSyncTask | 8,668.5 μs | 170.65 μs | 233.59 μs | 8,595.4 μs | 1.00 | 0.00 | - | - | - | - | +| SingleSyncTask_taskBuilder | SingleSyncTask | 12,402.4 μs | 103.89 μs | 92.10 μs | 12,366.7 μs | 1.43 | 0.04 | 9171.8750 | - | - | 48000000 B | +| SingleSyncTask_async | SingleSyncTask | 3,659,569.1 μs | 109,062.88 μs | 298,557.86 μs | 3,576,228.4 μs | 409.11 | 38.68 | 91000.0000 | - | - | 475999216 B | +| SingleSyncTask_task | SingleSyncTask | 10,642.1 μs | 90.05 μs | 84.23 μs | 10,622.2 μs | 1.23 | 0.04 | - | - | - | - | +| SingleSyncTask_async2 | SingleSyncTask | 28,177.5 μs | 263.90 μs | 220.37 μs | 28,134.6 μs | 3.25 | 0.08 | 7625.0000 | - | - | 40000000 B | +| | | | | | | | | | | | | +| SyncBuilderLoop_NormalCode | sync | 81,206.3 μs | 1,598.95 μs | 1,570.38 μs | 80,813.7 μs | 1.00 | 0.00 | 36714.2857 | - | - | 192176000 B | +| SyncBuilderLoop_WorkflowCode | sync | 81,811.3 μs | 1,610.38 μs | 3,140.93 μs | 80,621.9 μs | 1.02 | 0.05 | 36714.2857 | - | - | 192176000 B | +| | | | | | | | | | | | | +| TinyVariableSizedList_Builtin | TinyVariableSizedList | 57,762.3 μs | 1,721.40 μs | 4,827.00 μs | 56,313.5 μs | 1.00 | 0.00 | 20375.0000 | - | - | 106666656 B | +| TinyVariableSizedList_NewBuilder | TinyVariableSizedList | 17,122.1 μs | 341.76 μs | 650.23 μs | 17,233.0 μs | 0.29 | 0.03 | 2031.2500 | - | - | 10666656 B | +| | | | | | | | | | | | | +| VariableSizedList_Builtin | VariableSizedList | 330,273.8 μs | 6,534.98 μs | 13,051.05 μs | 328,659.3 μs | 1.00 | 0.00 | 63000.0000 | - | - | 330666624 B | +| VariableSizedList_NewBuilder | VariableSizedList | 167,451.6 μs | 2,840.89 μs | 2,217.98 μs | 167,326.7 μs | 0.51 | 0.02 | 44750.0000 | - | - | 234666934 B | +| | | | | | | | | | | | | +| FixedSizeList_Builtin | FixedSizedList | 100,128.5 μs | 1,968.29 μs | 3,885.21 μs | 100,084.8 μs | 1.00 | 0.00 | 61166.6667 | - | - | 320000000 B | +| FixedSizeList_NewBuilder | FixedSizedList | 229,639.0 μs | 4,589.37 μs | 11,846.63 μs | 227,278.1 μs | 2.30 | 0.13 | 61000.0000 | - | - | 320000000 B | +| | | | | | | | | | | | | +| TinyVariableSizedArray_Builtin | TinyVariableSizedArray | 100,414.3 μs | 1,995.07 μs | 4,462.26 μs | 100,631.3 μs | 1.00 | 0.00 | 30000.0000 | - | - | 157333304 B | +| TinyVariableSizedArray_NewBuilder | TinyVariableSizedArray | 28,538.5 μs | 632.86 μs | 1,825.93 μs | 28,426.7 μs | 0.29 | 0.02 | 10687.5000 | - | - | 55999968 B | +| | | | | | | | | | | | | +| VariableSizedArray_Builtin | VariableSizedArray | 356,489.5 μs | 3,061.89 μs | 2,714.29 μs | 356,174.5 μs | 1.00 | 0.00 | 77000.0000 | - | - | 405333840 B | +| VariableSizedArray_NewBuilder | VariableSizedArray | 161,909.3 μs | 861.02 μs | 672.23 μs | 161,860.8 μs | 0.45 | 0.00 | 59000.0000 | - | - | 309333476 B | +| | | | | | | | | | | | | +| FixedSizeArray_Builtin | FixedSizedArray | 32,944.8 μs | 777.85 μs | 2,293.52 μs | 32,391.8 μs | 1.00 | 0.00 | 19875.0000 | - | - | 104000000 B | +| FixedSizeArray_NewBuilder | FixedSizedArray | 219,352.6 μs | 4,288.40 μs | 10,837.34 μs | 217,830.4 μs | 6.65 | 0.60 | 82333.3333 | - | - | 432000000 B | +| | | | | | | | | | | | | +| MultiStepOption_OldBuilder | MultiStepOption | 63,360.5 μs | 1,199.04 μs | 1,062.92 μs | 63,133.5 μs | 1.00 | 0.00 | 38750.0000 | - | - | 202666703 B | +| MultiStepOption_NewBuilder | MultiStepOption | 20,179.8 μs | 622.44 μs | 1,775.86 μs | 19,705.5 μs | 0.29 | 0.02 | 13437.5000 | - | - | 70399968 B | +| MultiStepOption_NoBuilder | MultiStepOption | 19,727.8 μs | 469.72 μs | 1,362.75 μs | 19,395.3 μs | 0.32 | 0.02 | 13437.5000 | - | - | 70399968 B | +| | | | | | | | | | | | | +| MultiStepValueOption_OldBuilder | MultiStepValueOption | 47,237.3 μs | 909.93 μs | 759.83 μs | 47,211.0 μs | 1.00 | 0.00 | 19090.9091 | - | - | 100266664 B | +| MultiStepValueOption_NewBuilder | MultiStepValueOption | 4,144.6 μs | 46.31 μs | 43.32 μs | 4,146.1 μs | 0.09 | 0.00 | - | - | - | - | +| MultiStepValueOption_NoBuilder | MultiStepValueOption | 3,824.0 μs | 75.26 μs | 73.92 μs | 3,806.3 μs | 0.08 | 0.00 | - | - | - | - | +| | | | | | | | | | | | | +| NestedForLoops_taskSeqUsingRawResumableCode | taskSeq | 983.7 μs | 18.23 μs | 17.90 μs | 984.7 μs | 1.61 | 0.04 | 54.6875 | - | - | 295641 B | +| NestedForLoops_CSharpAsyncEnumerable | taskSeq | 612.9 μs | 10.04 μs | 8.90 μs | 615.5 μs | 1.00 | 0.00 | 24.4141 | - | - | 131280 B | diff --git a/FSharp.sln b/FSharp.sln index bcbb76848ae..2b07028feb2 100644 --- a/FSharp.sln +++ b/FSharp.sln @@ -60,17 +60,21 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Service.Tes EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Service", "src\fsharp\FSharp.Compiler.Service\FSharp.Compiler.Service.fsproj", "{9B4CF83C-C215-4EA0-9F8B-B5A77090F634}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FSharp.Compiler.Service.Tests support", "FSharp.Compiler.Service.Tests support", "{452EED3C-AA87-471F-B9AC-0F4479C5820C}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmarks", "Benchmarks", "{CE70D631-C5DC-417E-9CDA-B16097BEF1AC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharp_Analysis", "tests\service\data\CSharp_Analysis\CSharp_Analysis.csproj", "{F8743670-C8D4-41B3-86BE-BBB1226C352F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroPerfCSharp", "tests\benchmarks\MicroPerf\CS\MicroPerfCSharp.csproj", "{348DCC13-DD3E-4214-B040-5A74E8C6B782}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TestTP", "tests\service\data\TestTP\TestTP.fsproj", "{7BFA159A-BF9D-4489-BF46-1B83ACCEEE0F}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "MicroPerf", "tests\benchmarks\MicroPerf\MicroPerf.fsproj", "{9735B522-37F7-478C-A0C6-6C60BCC53390}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TaskPerfCSharp", "tests\benchmarks\TaskPerfCSharp\TaskPerfCSharp.csproj", "{CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmarks", "Benchmarks", "{E02ADBCA-D6C0-4898-A8AA-86DE6EBE2DC2}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TaskPerf", "tests\benchmarks\TaskPerf\TaskPerf.fsproj", "{51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroPerfCSharp", "tests\benchmarks\MicroPerf\CS\MicroPerfCSharp.csproj", "{2904313F-7782-4522-894C-DC946DFFE22D}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FSharp.Compiler.Service.Tests support", "FSharp.Compiler.Service.Tests support", "{452EED3C-AA87-471F-B9AC-0F4479C5820C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharp_Analysis", "tests\service\data\CSharp_Analysis\CSharp_Analysis.csproj", "{F8743670-C8D4-41B3-86BE-BBB1226C352F}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "MicroPerf", "tests\benchmarks\MicroPerf\MicroPerf.fsproj", "{C888A81D-2372-4B4A-8BA1-525AEE3918D6}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TestTP", "tests\service\data\TestTP\TestTP.fsproj", "{7BFA159A-BF9D-4489-BF46-1B83ACCEEE0F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -310,6 +314,54 @@ Global {9B4CF83C-C215-4EA0-9F8B-B5A77090F634}.Release|Any CPU.Build.0 = Release|Any CPU {9B4CF83C-C215-4EA0-9F8B-B5A77090F634}.Release|x86.ActiveCfg = Release|Any CPU {9B4CF83C-C215-4EA0-9F8B-B5A77090F634}.Release|x86.Build.0 = Release|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Debug|Any CPU.Build.0 = Debug|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Debug|x86.ActiveCfg = Debug|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Debug|x86.Build.0 = Debug|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Proto|Any CPU.Build.0 = Debug|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Proto|x86.ActiveCfg = Debug|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Proto|x86.Build.0 = Debug|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Release|Any CPU.ActiveCfg = Release|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Release|Any CPU.Build.0 = Release|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Release|x86.ActiveCfg = Release|Any CPU + {348DCC13-DD3E-4214-B040-5A74E8C6B782}.Release|x86.Build.0 = Release|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Debug|x86.ActiveCfg = Debug|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Debug|x86.Build.0 = Debug|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Proto|Any CPU.Build.0 = Debug|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Proto|x86.ActiveCfg = Debug|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Proto|x86.Build.0 = Debug|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Release|Any CPU.Build.0 = Release|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Release|x86.ActiveCfg = Release|Any CPU + {9735B522-37F7-478C-A0C6-6C60BCC53390}.Release|x86.Build.0 = Release|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Debug|x86.ActiveCfg = Debug|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Debug|x86.Build.0 = Debug|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Proto|Any CPU.Build.0 = Debug|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Proto|x86.ActiveCfg = Debug|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Proto|x86.Build.0 = Debug|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Release|Any CPU.Build.0 = Release|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Release|x86.ActiveCfg = Release|Any CPU + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB}.Release|x86.Build.0 = Release|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Debug|x86.ActiveCfg = Debug|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Debug|x86.Build.0 = Debug|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Proto|Any CPU.Build.0 = Debug|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Proto|x86.ActiveCfg = Debug|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Proto|x86.Build.0 = Debug|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Release|Any CPU.Build.0 = Release|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Release|x86.ActiveCfg = Release|Any CPU + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4}.Release|x86.Build.0 = Release|Any CPU {F8743670-C8D4-41B3-86BE-BBB1226C352F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F8743670-C8D4-41B3-86BE-BBB1226C352F}.Debug|Any CPU.Build.0 = Debug|Any CPU {F8743670-C8D4-41B3-86BE-BBB1226C352F}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -334,35 +386,12 @@ Global {7BFA159A-BF9D-4489-BF46-1B83ACCEEE0F}.Release|Any CPU.Build.0 = Release|Any CPU {7BFA159A-BF9D-4489-BF46-1B83ACCEEE0F}.Release|x86.ActiveCfg = Release|Any CPU {7BFA159A-BF9D-4489-BF46-1B83ACCEEE0F}.Release|x86.Build.0 = Release|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Debug|x86.ActiveCfg = Debug|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Debug|x86.Build.0 = Debug|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Proto|Any CPU.ActiveCfg = Debug|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Proto|Any CPU.Build.0 = Debug|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Proto|x86.ActiveCfg = Debug|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Proto|x86.Build.0 = Debug|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Release|Any CPU.Build.0 = Release|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Release|x86.ActiveCfg = Release|Any CPU - {2904313F-7782-4522-894C-DC946DFFE22D}.Release|x86.Build.0 = Release|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Debug|x86.ActiveCfg = Debug|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Debug|x86.Build.0 = Debug|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Proto|Any CPU.ActiveCfg = Debug|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Proto|Any CPU.Build.0 = Debug|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Proto|x86.ActiveCfg = Debug|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Proto|x86.Build.0 = Debug|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Release|Any CPU.Build.0 = Release|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Release|x86.ActiveCfg = Release|Any CPU - {C888A81D-2372-4B4A-8BA1-525AEE3918D6}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution + {D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06} = {B8DDA694-7939-42E3-95E5-265C2217C142} {DED3BBD7-53F4-428A-8C9F-27968E768605} = {3058BC79-8E79-4645-B05D-48CC182FA8A6} {702A7979-BCF9-4C41-853E-3ADFC9897890} = {B8DDA694-7939-42E3-95E5-265C2217C142} {C94C257C-3C0A-4858-B5D8-D746498D1F08} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} @@ -384,11 +413,13 @@ Global {25568CD2-E654-4C8F-BE5B-59BABFC5BD20} = {07482B5E-4980-4285-B732-820F15870284} {DDFD06DC-D7F2-417F-9177-107764EEBCD8} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {9B4CF83C-C215-4EA0-9F8B-B5A77090F634} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} + {348DCC13-DD3E-4214-B040-5A74E8C6B782} = {CE70D631-C5DC-417E-9CDA-B16097BEF1AC} + {9735B522-37F7-478C-A0C6-6C60BCC53390} = {CE70D631-C5DC-417E-9CDA-B16097BEF1AC} + {CF9F3F98-7BFB-4945-A4A5-668DF0AC65AB} = {CE70D631-C5DC-417E-9CDA-B16097BEF1AC} + {51B569A8-17C5-4EBD-8AAC-240E0B3AD8C4} = {CE70D631-C5DC-417E-9CDA-B16097BEF1AC} {452EED3C-AA87-471F-B9AC-0F4479C5820C} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {F8743670-C8D4-41B3-86BE-BBB1226C352F} = {452EED3C-AA87-471F-B9AC-0F4479C5820C} {7BFA159A-BF9D-4489-BF46-1B83ACCEEE0F} = {452EED3C-AA87-471F-B9AC-0F4479C5820C} - {2904313F-7782-4522-894C-DC946DFFE22D} = {E02ADBCA-D6C0-4898-A8AA-86DE6EBE2DC2} - {C888A81D-2372-4B4A-8BA1-525AEE3918D6} = {E02ADBCA-D6C0-4898-A8AA-86DE6EBE2DC2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BD5177C7-1380-40E7-94D2-7768E1A8B1B8} diff --git a/FSharpBuild.Directory.Build.props b/FSharpBuild.Directory.Build.props index 767e0da6ebc..bcdbffa1c12 100644 --- a/FSharpBuild.Directory.Build.props +++ b/FSharpBuild.Directory.Build.props @@ -87,4 +87,13 @@ $(ProtoOutputPath)\fsc\Microsoft.FSharp.Overrides.NetSdk.targets + + + diff --git a/VisualFSharp.sln b/VisualFSharp.sln index d35c1ba10b9..a51b52cc044 100644 --- a/VisualFSharp.sln +++ b/VisualFSharp.sln @@ -152,6 +152,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibraryProject", "vsintegra EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TutorialProject", "vsintegration\ProjectTemplates\TutorialProject\TutorialProject.csproj", "{2937CBEC-262D-4C94-BE1D-291FAB72E3E8}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TaskPerfCSharp", "tests\benchmarks\TaskPerfCSharp\TaskPerfCSharp.csproj", "{D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}" +EndProject +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TaskPerf", "tests\benchmarks\TaskPerf\TaskPerf.fsproj", "{03596D51-754D-4644-8E23-84EC9532ABDC}" +EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.ComponentTests", "tests\FSharp.Compiler.ComponentTests\FSharp.Compiler.ComponentTests.fsproj", "{0610FB97-7C15-422A-86FD-32335C6DF14D}" EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharp.Compiler.Service", "src\fsharp\FSharp.Compiler.Service\FSharp.Compiler.Service.fsproj", "{B5A9BBD9-2F45-4722-A6CA-BAE3C64CD4E2}" @@ -904,6 +908,30 @@ Global {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Release|Any CPU.Build.0 = Release|Any CPU {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Release|x86.ActiveCfg = Release|Any CPU {2937CBEC-262D-4C94-BE1D-291FAB72E3E8}.Release|x86.Build.0 = Release|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Debug|x86.ActiveCfg = Debug|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Debug|x86.Build.0 = Debug|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Proto|Any CPU.Build.0 = Debug|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Proto|x86.ActiveCfg = Debug|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Proto|x86.Build.0 = Debug|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Release|Any CPU.Build.0 = Release|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Release|x86.ActiveCfg = Release|Any CPU + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0}.Release|x86.Build.0 = Release|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Debug|x86.ActiveCfg = Debug|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Debug|x86.Build.0 = Debug|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Proto|Any CPU.ActiveCfg = Debug|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Proto|Any CPU.Build.0 = Debug|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Proto|x86.ActiveCfg = Debug|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Proto|x86.Build.0 = Debug|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Release|Any CPU.Build.0 = Release|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Release|x86.ActiveCfg = Release|Any CPU + {03596D51-754D-4644-8E23-84EC9532ABDC}.Release|x86.Build.0 = Release|Any CPU {0610FB97-7C15-422A-86FD-32335C6DF14D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0610FB97-7C15-422A-86FD-32335C6DF14D}.Debug|Any CPU.Build.0 = Debug|Any CPU {0610FB97-7C15-422A-86FD-32335C6DF14D}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -1059,6 +1087,8 @@ Global {44155269-9B30-43DA-B97F-4F36F887B211} = {12EF27FD-A34B-4373-860A-F9FCE9651859} {B53D9D05-8EF7-43A6-9A5B-0B113CBC54F8} = {12EF27FD-A34B-4373-860A-F9FCE9651859} {2937CBEC-262D-4C94-BE1D-291FAB72E3E8} = {12EF27FD-A34B-4373-860A-F9FCE9651859} + {D5ECF8DF-E150-4AE3-B613-AB2B0FFA93E0} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} + {03596D51-754D-4644-8E23-84EC9532ABDC} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {0610FB97-7C15-422A-86FD-32335C6DF14D} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} {B5A9BBD9-2F45-4722-A6CA-BAE3C64CD4E2} = {3881429D-A97A-49EB-B7AE-A82BA5FE9C77} {14F3D3D6-5C8E-43C2-98A2-17EA704D4DEA} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449} diff --git a/src/fsharp/CheckComputationExpressions.fs b/src/fsharp/CheckComputationExpressions.fs index fc3d9ace548..df0d2e4c278 100644 --- a/src/fsharp/CheckComputationExpressions.fs +++ b/src/fsharp/CheckComputationExpressions.fs @@ -857,7 +857,7 @@ let TcComputationExpression cenv env overallTy tpenv (mWhole, interpExpr: Expr, // 2. incompatible types: int and string // with SynExpr.ArbitraryAfterError we have only first one let wrapInArbErrSequence l caption = - SynExpr.Sequential (DebugPointAtSequential.Both, true, l, (arbExpr(caption, l.Range.EndRange)), l.Range) + SynExpr.Sequential (DebugPointAtSequential.SuppressNeither, true, l, (arbExpr(caption, l.Range.EndRange)), l.Range) let mkOverallExprGivenVarSpaceExpr, varSpaceInner = let isNullableOp opId = @@ -929,7 +929,7 @@ let TcComputationExpression cenv env overallTy tpenv (mWhole, interpExpr: Expr, | SynExpr.ForEach (spForLoop, SeqExprOnly _seqExprOnly, isFromSource, pat, sourceExpr, innerComp, _) -> let wrappedSourceExpr = mkSourceExprConditional isFromSource sourceExpr - let mFor = match spForLoop with DebugPointAtFor.Yes m -> m | _ -> pat.Range + let mFor = match spForLoop with DebugPointAtFor.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.For) | _ -> pat.Range let mPat = pat.Range let spBind = match spForLoop with DebugPointAtFor.Yes m -> DebugPointAtBinding.Yes m | DebugPointAtFor.No -> DebugPointAtBinding.NoneAtSticky if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mFor ad "For" builderTy) then @@ -947,13 +947,13 @@ let TcComputationExpression cenv env overallTy tpenv (mWhole, interpExpr: Expr, translatedCtxt (mkSynCall "For" mFor [wrappedSourceExpr; SynExpr.MatchLambda (false, sourceExpr.Range, [SynMatchClause(pat, None, holeFill, mPat, DebugPointForTarget.Yes)], spBind, mFor) ])) ) | SynExpr.For (spBind, id, start, dir, finish, innerComp, m) -> - let mFor = match spBind with DebugPointAtFor.Yes m -> m | _ -> m + let mFor = match spBind with DebugPointAtFor.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.For) | _ -> m if isQuery then errorR(Error(FSComp.SR.tcNoIntegerForLoopInQuery(), mFor)) Some (trans CompExprTranslationPass.Initial q varSpace (elimFastIntegerForLoop (spBind, id, start, dir, finish, innerComp, m)) translatedCtxt ) | SynExpr.While (spWhile, guardExpr, innerComp, _) -> let mGuard = guardExpr.Range - let mWhile = match spWhile with DebugPointAtWhile.Yes m -> m | _ -> mGuard + let mWhile = match spWhile with DebugPointAtWhile.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.While) | _ -> mGuard if isQuery then error(Error(FSComp.SR.tcNoWhileInQuery(), mWhile)) if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mWhile ad "While" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("While"), mWhile)) @@ -963,7 +963,7 @@ let TcComputationExpression cenv env overallTy tpenv (mWhole, interpExpr: Expr, | SynExpr.TryFinally (innerComp, unwindExpr, mTryToLast, spTry, _spFinally) -> - let mTry = match spTry with DebugPointAtTry.Yes m -> m | _ -> mTryToLast + let mTry = match spTry with DebugPointAtTry.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.Try) | _ -> mTryToLast if isQuery then error(Error(FSComp.SR.tcNoTryFinallyInQuery(), mTry)) if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env mTry ad "TryFinally" builderTy) then error(Error(FSComp.SR.tcRequireBuilderMethod("TryFinally"), mTry)) @@ -1048,9 +1048,10 @@ let TcComputationExpression cenv env overallTy tpenv (mWhole, interpExpr: Expr, | SynExpr.DoBang (rhsExpr, m) -> let sp = match sp with - | DebugPointAtSequential.ExprOnly -> DebugPointAtBinding.Yes m - | DebugPointAtSequential.StmtOnly -> DebugPointAtBinding.NoneAtDo - | DebugPointAtSequential.Both -> DebugPointAtBinding.Yes m + | DebugPointAtSequential.SuppressExpr -> DebugPointAtBinding.NoneAtDo + | DebugPointAtSequential.SuppressBoth -> DebugPointAtBinding.NoneAtDo + | DebugPointAtSequential.SuppressStmt -> DebugPointAtBinding.Yes m + | DebugPointAtSequential.SuppressNeither -> DebugPointAtBinding.Yes m Some(trans CompExprTranslationPass.Initial q varSpace (SynExpr.LetOrUseBang (sp, false, true, SynPat.Const(SynConst.Unit, rhsExpr.Range), rhsExpr, [], innerComp2, m)) translatedCtxt) // "expr; cexpr" is treated as sequential execution @@ -1298,7 +1299,7 @@ let TcComputationExpression cenv env overallTy tpenv (mWhole, interpExpr: Expr, Some(translatedCtxt (mkSynCall "Bind" mMatch [matchExpr; consumeExpr])) | SynExpr.TryWith (innerComp, _mTryToWith, clauses, _mWithToLast, mTryToLast, spTry, _spWith) -> - let mTry = match spTry with DebugPointAtTry.Yes m -> m | _ -> mTryToLast + let mTry = match spTry with DebugPointAtTry.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.Try) | _ -> mTryToLast if isQuery then error(Error(FSComp.SR.tcTryWithMayNotBeUsedInQueries(), mTry)) let clauses = clauses |> List.map (fun (SynMatchClause(pat, cond, clauseComp, patm, sp)) -> SynMatchClause(pat, cond, transNoQueryOps clauseComp, patm, sp)) @@ -1456,7 +1457,7 @@ let TcComputationExpression cenv env overallTy tpenv (mWhole, interpExpr: Expr, | None -> // This only occurs in final position in a sequence match comp with - // "do! expr;" in final position is treated as { let! () = expr in return () } when Return is provided or as { let! () = expr in zero } otherwise + // "do! expr;" in final position is treated as { let! () = expr in return () } when Return is provided (and no Zero with Default attribute is available) or as { let! () = expr in zero } otherwise | SynExpr.DoBang (rhsExpr, m) -> let mUnit = rhsExpr.Range let rhsExpr = mkSourceExpr rhsExpr @@ -1465,7 +1466,9 @@ let TcComputationExpression cenv env overallTy tpenv (mWhole, interpExpr: Expr, if isNil (TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Return" builderTy) then SynExpr.ImplicitZero m else - SynExpr.YieldOrReturn((false, true), SynExpr.Const(SynConst.Unit, m), m) + match TryFindIntrinsicOrExtensionMethInfo ResultCollectionSettings.AtMostOneResult cenv env m ad "Zero" builderTy with + | minfo :: _ when MethInfoHasAttribute cenv.g m cenv.g.attrib_DefaultValueAttribute minfo -> SynExpr.ImplicitZero m + | _ -> SynExpr.YieldOrReturn ((false, true), SynExpr.Const (SynConst.Unit, m), m) trans CompExprTranslationPass.Initial q varSpace (SynExpr.LetOrUseBang (DebugPointAtBinding.NoneAtDo, false, false, SynPat.Const(SynConst.Unit, mUnit), rhsExpr, [], bodyExpr, m)) translatedCtxt // "expr;" in final position is treated as { expr; zero } @@ -1483,9 +1486,9 @@ let TcComputationExpression cenv env overallTy tpenv (mWhole, interpExpr: Expr, let fillExpr = if enableImplicitYield then let implicitYieldExpr = mkSynCall "Yield" comp.Range [comp] - SynExpr.SequentialOrImplicitYield(DebugPointAtSequential.ExprOnly, comp, holeFill, implicitYieldExpr, comp.Range) + SynExpr.SequentialOrImplicitYield(DebugPointAtSequential.SuppressExpr, comp, holeFill, implicitYieldExpr, comp.Range) else - SynExpr.Sequential(DebugPointAtSequential.ExprOnly, true, comp, holeFill, comp.Range) + SynExpr.Sequential(DebugPointAtSequential.SuppressExpr, true, comp, holeFill, comp.Range) translatedCtxt fillExpr) and transBind q varSpace bindRange bindName bindArgs (consumePat: SynPat) spBind (innerComp: SynExpr) translatedCtxt = @@ -1688,7 +1691,7 @@ let mkSeqFinally (cenv: cenv) env m genTy e1 e2 = mkCallSeqFinally cenv.g m genResultTy e1 e2 let mkSeqExprMatchClauses (pat', vspecs) innerExpr = - [TClause(pat', None, TTarget(vspecs, innerExpr, DebugPointForTarget.Yes), pat'.Range) ] + [TClause(pat', None, TTarget(vspecs, innerExpr, DebugPointForTarget.Yes, None), pat'.Range) ] let compileSeqExprMatchClauses (cenv: cenv) env inputExprMark (pat: Pattern, vspecs) innerExpr inputExprOpt bindPatTy genInnerTy = let patMark = pat.Range @@ -1733,7 +1736,7 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp overallTy m = // We attach the debug point to the lambda expression so we can fetch it out again in LowerComputedListOrArraySeqExpr let mFor = match spFor with - | DebugPointAtFor.Yes m -> m + | DebugPointAtFor.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.For) | _ -> enumExprMark match pat', vspecs, innerExpr with @@ -1771,7 +1774,7 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp overallTy m = // We attach the debug point to the lambda expression so we can fetch it out again in LowerComputedListOrArraySeqExpr let mWhile = match spWhile with - | DebugPointAtWhile.Yes m -> m + | DebugPointAtWhile.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.While) | _ -> guardExprMark let innerExpr = mkDelayedExpr mWhile innerExpr @@ -1784,12 +1787,12 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp overallTy m = // We attach the debug points to the lambda expressions so we can fetch it out again in LowerComputedListOrArraySeqExpr let mTry = match spTry with - | DebugPointAtTry.Yes m -> m + | DebugPointAtTry.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.Try) | _ -> unwindExpr.Range let mFinally = match spFinally with - | DebugPointAtFinally.Yes m -> m + | DebugPointAtFinally.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.Finally) | _ -> unwindExpr.Range let innerExpr = mkDelayedExpr mTry innerExpr @@ -1847,7 +1850,7 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp overallTy m = let innerExpr, tpenv = tcSequenceExprBody envinner genOuterTy tpenv innerComp let mBind = match spBind with - | DebugPointAtBinding.Yes m -> m + | DebugPointAtBinding.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.Binding) | _ -> inputExpr.Range let inputExprMark = inputExpr.Range let matchv, matchExpr = compileSeqExprMatchClauses cenv env inputExprMark (pat', vspecs) innerExpr (Some inputExpr) bindPatTy genOuterTy @@ -1865,7 +1868,7 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp overallTy m = (fun tpenv (SynMatchClause(pat, cond, innerComp, _, sp)) -> let pat', cond', vspecs, envinner, tpenv = TcMatchPattern cenv matchty env tpenv (pat, cond) let innerExpr, tpenv = tcSequenceExprBody envinner genOuterTy tpenv innerComp - TClause(pat', cond', TTarget(vspecs, innerExpr, sp), pat'.Range), tpenv) + TClause(pat', cond', TTarget(vspecs, innerExpr, sp, None), pat'.Range), tpenv) tpenv clauses let inputExprTy = tyOfExpr cenv.g inputExpr @@ -1901,7 +1904,7 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp overallTy m = expr, tpenv | Choice2Of2 stmt -> let m = comp.Range - let resExpr = Expr.Sequential(stmt, mkSeqEmpty cenv env m genOuterTy, NormalSeq, DebugPointAtSequential.ExprOnly, m) + let resExpr = Expr.Sequential(stmt, mkSeqEmpty cenv env m genOuterTy, NormalSeq, DebugPointAtSequential.SuppressExpr, m) resExpr, tpenv and tcSequenceExprBodyAsSequenceOrStatement env genOuterTy tpenv comp = diff --git a/src/fsharp/CheckDeclarations.fs b/src/fsharp/CheckDeclarations.fs index adeeb809e7f..eb492fccc0e 100644 --- a/src/fsharp/CheckDeclarations.fs +++ b/src/fsharp/CheckDeclarations.fs @@ -1299,7 +1299,7 @@ module IncrClassChecking = (isPriorToSuperInit, (fun e -> let e = match adjustSafeInitFieldExprOpt with None -> e | Some ae -> mkCompGenSequential m ae e - mkSequential DebugPointAtSequential.Both m assignExpr e)), [] + mkSequential DebugPointAtSequential.SuppressNeither m assignExpr e)), [] /// Work out the implicit construction side effects of a 'let', 'let rec' or 'do' /// binding in the implicit class construction sequence @@ -1327,7 +1327,7 @@ module IncrClassChecking = | IncrClassDo (doExpr, isStatic) -> let doExpr = reps.FixupIncrClassExprPhase2C cenv (Some thisVal) safeStaticInitInfo thisTyInst doExpr - let binder = (fun e -> mkSequential DebugPointAtSequential.Both doExpr.Range doExpr e) + let binder = (fun e -> mkSequential DebugPointAtSequential.SuppressNeither doExpr.Range doExpr e) let isPriorToSuperInit = false if isStatic then ([(isPriorToSuperInit, binder)], [], []), reps @@ -1347,7 +1347,7 @@ module IncrClassChecking = | Some v -> let setExpr = mkRefCellSet g m ctorInfo.InstanceCtorThisVal.Type (exprForVal m v) (exprForVal m ctorInfo.InstanceCtorThisVal) let setExpr = reps.FixupIncrClassExprPhase2C cenv (Some thisVal) safeStaticInitInfo thisTyInst setExpr - let binder = (fun e -> mkSequential DebugPointAtSequential.Both setExpr.Range setExpr e) + let binder = (fun e -> mkSequential DebugPointAtSequential.SuppressNeither setExpr.Range setExpr e) let isPriorToSuperInit = false yield (isPriorToSuperInit, binder) ] @@ -1361,7 +1361,7 @@ module IncrClassChecking = | SafeInitField (rfref, _) -> let setExpr = mkRecdFieldSetViaExprAddr (exprForVal m thisVal, rfref, thisTyInst, mkOne g m, m) let setExpr = reps.FixupIncrClassExprPhase2C cenv (Some thisVal) safeStaticInitInfo thisTyInst setExpr - let binder = (fun e -> mkSequential DebugPointAtSequential.Both setExpr.Range setExpr e) + let binder = (fun e -> mkSequential DebugPointAtSequential.SuppressNeither setExpr.Range setExpr e) let isPriorToSuperInit = false yield (isPriorToSuperInit, binder) | NoSafeInitInfo -> @@ -1448,7 +1448,7 @@ module IncrClassChecking = | _ -> inheritsExpr - let spAtSuperInit = (if inheritsIsVisible then DebugPointAtSequential.Both else DebugPointAtSequential.StmtOnly) + let spAtSuperInit = (if inheritsIsVisible then DebugPointAtSequential.SuppressNeither else DebugPointAtSequential.SuppressStmt) mkSequential spAtSuperInit m inheritsExpr ctorBody // Add the normal @@ -5662,7 +5662,8 @@ let emptyTcEnv g = eModuleOrNamespaceTypeAccumulator = ref (Construct.NewEmptyModuleOrNamespaceType Namespace) eFamilyType = None eCtorInfo = None - eCallerMemberName = None } + eCallerMemberName = None + eLambdaArgInfos = [] } let CreateInitialTcEnv(g, amap, scopem, assemblyName, ccus) = (emptyTcEnv g, ccus) ||> List.fold (fun env (ccu, autoOpens, internalsVisible) -> diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index 3babb1945f1..21a9375b6a1 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -215,6 +215,9 @@ type TcEnv = eCtorInfo: CtorInfo option eCallerMemberName: string option + + // Active arg infos in iterated lambdas , allowing us to determine the attributes of arguments + eLambdaArgInfos: ArgReprInfo list list } member tenv.DisplayEnv = tenv.eNameResEnv.DisplayEnv @@ -1333,13 +1336,13 @@ let MakeAndPublishVal cenv env (altActualParent, inSig, declKind, vrec, vscheme, let vis, _ = ComputeAccessAndCompPath env (Some declKind) id.idRange vis overrideVis actualParent - let inlineFlag = - if HasFSharpAttributeOpt cenv.g cenv.g.attrib_DllImportAttribute attrs then - if inlineFlag = ValInline.PseudoVal || inlineFlag = ValInline.Always then - errorR(Error(FSComp.SR.tcDllImportStubsCannotBeInlined(), m)) - ValInline.Never - else - let implflags = + let inlineFlag = + if HasFSharpAttributeOpt cenv.g cenv.g.attrib_DllImportAttribute attrs then + if inlineFlag = ValInline.Always then + errorR(Error(FSComp.SR.tcDllImportStubsCannotBeInlined(), m)) + ValInline.Never + else + let implflags = match TryFindFSharpAttribute cenv.g cenv.g.attrib_MethodImplAttribute attrs with | Some (Attrib(_, _, [ AttribInt32Arg flags ], _, _, _, _)) -> flags | _ -> 0x0 @@ -1657,7 +1660,10 @@ let CombineSyntacticAndInferredArities g declKind rhsExpr prelimScheme = // Don't use any expression information for members, where syntax dictates the arity completely | _ when memberInfoOpt.IsSome -> partialValReprInfoOpt - | Some partialValReprInfoFromSyntax, true -> + // Don't use any expression information for 'let' bindings where return attributes are present + | _ when retAttribs.Length > 0 -> + partialValReprInfoOpt + | Some partialValReprInfoFromSyntax, true -> let (PartialValReprInfo(curriedArgInfosFromSyntax, retInfoFromSyntax)) = partialValReprInfoFromSyntax let partialArityInfo = if isMutable then @@ -2045,12 +2051,12 @@ module GeneralizationHelpers = /// Recursively knock out typars we can't generalize. /// For non-generalized type variables be careful to iteratively knock out /// both the typars and any typars free in the constraints of the typars - /// into the set that are considered free in the environment. - let rec TrimUngeneralizableTypars genConstrainedTyparFlag inlineFlag (generalizedTypars: Typar list) freeInEnv = - // Do not generalize type variables with a static requirement unless function is marked 'inline' - let generalizedTypars, ungeneralizableTypars1 = - if inlineFlag = ValInline.PseudoVal then generalizedTypars, [] - else generalizedTypars |> List.partition (fun tp -> tp.StaticReq = TyparStaticReq.None) + /// into the set that are considered free in the environment. + let rec TrimUngeneralizableTypars genConstrainedTyparFlag inlineFlag (generalizedTypars: Typar list) freeInEnv = + // Do not generalize type variables with a static requirement unless function is marked 'inline' + let generalizedTypars, ungeneralizableTypars1 = + if inlineFlag = ValInline.Always then generalizedTypars, [] + else generalizedTypars |> List.partition (fun tp -> tp.StaticReq = TyparStaticReq.None) // Do not generalize type variables which would escape their scope // because they are free in the environment @@ -2234,11 +2240,11 @@ let ComputeInlineFlag (memFlagsOption: SynMemberFlags option) isInline isMutable if isMutable || (match memFlagsOption with | None -> false - | Some x -> (x.MemberKind = SynMemberKind.Constructor) || x.IsDispatchSlot || x.IsOverrideOrExplicitImpl) - then ValInline.Never - elif isInline then ValInline.PseudoVal + | Some x -> (x.MemberKind = SynMemberKind.Constructor) || x.IsDispatchSlot || x.IsOverrideOrExplicitImpl) + then ValInline.Never + elif isInline then ValInline.Always else ValInline.Optional - if isInline && (inlineFlag <> ValInline.PseudoVal) then + if isInline && (inlineFlag <> ValInline.Always) then errorR(Error(FSComp.SR.tcThisValueMayNotBeInlined(), m)) inlineFlag @@ -2314,10 +2320,10 @@ type IsObjExprBinding = | ValOrMemberBinding module BindingNormalization = - /// Push a bunch of pats at once. They may contain patterns, e.g. let f (A x) (B y) = ... - /// In this case the semantics is let f a b = let A x = a in let B y = b - let private PushMultiplePatternsToRhs (cenv: cenv) isMember ps (NormalizedBindingRhs(spatsL, rtyOpt, rhsExpr)) = - let spatsL2, rhsExpr = PushCurriedPatternsToExpr cenv.synArgNameGenerator rhsExpr.Range isMember ps rhsExpr + /// Push a bunch of pats at once. They may contain patterns, e.g. let f (A x) (B y) = ... + /// In this case the semantics is let f a b = let A x = a in let B y = b + let private PushMultiplePatternsToRhs (cenv: cenv) isMember pats (NormalizedBindingRhs(spatsL, rtyOpt, rhsExpr)) = + let spatsL2, rhsExpr = PushCurriedPatternsToExpr cenv.synArgNameGenerator rhsExpr.Range isMember pats rhsExpr NormalizedBindingRhs(spatsL2@spatsL, rtyOpt, rhsExpr) @@ -3083,12 +3089,13 @@ let CompilePatternForMatch cenv (env: TcEnv) mExpr matchm warnOnUnused actionOnF mkAndSimplifyMatch DebugPointAtBinding.NoneAtInvisible mExpr matchm resultTy dtree targets /// Compile a pattern -let CompilePatternForMatchClauses cenv env mExpr matchm warnOnUnused actionOnFailure inputExprOpt inputTy resultTy tclauses = - // Avoid creating a dummy in the common cases where we are about to bind a name for the expression - // CLEANUP: avoid code duplication with code further below, i.e.all callers should call CompilePatternForMatch - match tclauses with - | [TClause(TPat_as (pat1, PBind (asVal, TypeScheme(generalizedTypars, _)), _), None, TTarget(vs, e, spTarget), m2)] -> - let expr = CompilePatternForMatch cenv env mExpr matchm warnOnUnused actionOnFailure (asVal, generalizedTypars, None) [TClause(pat1, None, TTarget(ListSet.remove valEq asVal vs, e, spTarget), m2)] inputTy resultTy +let CompilePatternForMatchClauses cenv env mExpr matchm warnOnUnused actionOnFailure inputExprOpt inputTy resultTy tclauses = + // Avoid creating a dummy in the common cases where we are about to bind a name for the expression + // CLEANUP: avoid code duplication with code further below, i.e.all callers should call CompilePatternForMatch + match tclauses with + | [TClause(TPat_as (pat1, PBind (asVal, TypeScheme(generalizedTypars, _)), _), None, TTarget(vs, e, spTarget, _), m2)] -> + let vs2 = ListSet.remove valEq asVal vs + let expr = CompilePatternForMatch cenv env mExpr matchm warnOnUnused actionOnFailure (asVal, generalizedTypars, None) [TClause(pat1, None, TTarget(vs2, e, spTarget, None), m2)] inputTy resultTy asVal, expr | _ -> let matchValueTmp, _ = mkCompGenLocal mExpr "matchValue" inputTy @@ -3350,9 +3357,9 @@ let EliminateInitializationGraphs | Expr.TyLambda (_, _, b, _, _) -> CheckExpr st b | Expr.Obj (_, ty, _, e, overrides, extraImpls, _) -> - // NOTE: we can't fixup recursive references inside delegates since the closure delegee of a delegate is not accessible - // from outside. Object expressions implementing interfaces can, on the other hand, be fixed up. See FSharp 1.0 bug 1469 - if isInterfaceTy g ty then + // NOTE: we can't fixup recursive references inside delegates since the closure delegee of a delegate is not accessible + // from outside. Object expressions implementing interfaces can, on the other hand, be fixed up. See FSharp 1.0 bug 1469 + if isInterfaceTy g ty then List.iter (fun (TObjExprMethod(_, _, _, _, e, _)) -> checkDelayed st e) overrides List.iter (snd >> List.iter (fun (TObjExprMethod(_, _, _, _, e, _)) -> checkDelayed st e)) extraImpls else @@ -3393,12 +3400,14 @@ let EliminateInitializationGraphs | Expr.Quote _ -> () | Expr.WitnessArg (_witnessInfo, _m) -> () - and CheckBinding st (TBind(_, e, _)) = CheckExpr st e + and CheckBinding st (TBind(_, e, _)) = CheckExpr st e + and CheckDecisionTree st = function | TDSwitch(e1, csl, dflt, _) -> CheckExpr st e1; List.iter (fun (TCase(_, d)) -> CheckDecisionTree st d) csl; Option.iter (CheckDecisionTree st) dflt | TDSuccess (es, _) -> es |> List.iter (CheckExpr st) | TDBind(bind, e) -> CheckBinding st bind; CheckDecisionTree st e - and CheckDecisionTreeTarget st (TTarget(_, e, _)) = CheckExpr st e + + and CheckDecisionTreeTarget st (TTarget(_, e, _, _)) = CheckExpr st e and CheckExprOp st op m = match op with @@ -3516,7 +3525,7 @@ let CheckAndRewriteObjectCtor g env (ctorLambdaExpr: Expr) = let ty = tyOfExpr g recdExpr let thisExpr = mkGetArg0 m ty let setExpr = mkRefCellSet g m ty (exprForValRef m (mkLocalValRef safeInitVal)) thisExpr - Expr.Sequential (recdExpr, setExpr, ThenDoSeq, DebugPointAtSequential.StmtOnly, m) + Expr.Sequential (recdExpr, setExpr, ThenDoSeq, DebugPointAtSequential.SuppressStmt, m) let recdExpr = match ctorInfo.safeInitInfo with | NoSafeInitInfo -> recdExpr @@ -3525,7 +3534,7 @@ let CheckAndRewriteObjectCtor g env (ctorLambdaExpr: Expr) = let thisExpr = mkGetArg0 m thisTy let thisTyInst = argsOfAppTy g thisTy let setExpr = mkRecdFieldSetViaExprAddr (thisExpr, rfref, thisTyInst, mkOne g m, m) - Expr.Sequential (recdExpr, setExpr, ThenDoSeq, DebugPointAtSequential.StmtOnly, m) + Expr.Sequential (recdExpr, setExpr, ThenDoSeq, DebugPointAtSequential.SuppressStmt, m) recdExpr @@ -3544,8 +3553,10 @@ let CheckAndRewriteObjectCtor g env (ctorLambdaExpr: Expr) = // = "let pat = expr in " | Expr.Let (bind, body, m, _) -> mkLetBind m bind (checkAndRewrite body) - // The constructor is a sequence "let pat = expr in " - | Expr.Match (spBind, a, b, targets, c, d) -> Expr.Match (spBind, a, b, (targets |> Array.map (fun (TTarget(vs, body, spTarget)) -> TTarget(vs, checkAndRewrite body, spTarget))), c, d) + // The constructor is a sequence "let pat = expr in " + | Expr.Match (spBind, a, b, targets, c, d) -> + let targets = targets |> Array.map (fun (TTarget(vs, body, spTarget, flags)) -> TTarget(vs, checkAndRewrite body, spTarget, flags)) + Expr.Match (spBind, a, b, targets, c, d) // = "let rec binds in " | Expr.LetRec (a, body, _, _) -> Expr.LetRec (a, checkAndRewrite body, m, Construct.NewFreeVarsCache()) @@ -5849,12 +5860,28 @@ and TcIteratedLambdas cenv isFirst (env: TcEnv) overallTy takenNames tpenv e = let envinner, _, vspecMap = MakeAndPublishSimpleValsForMergedScope cenv env m names let byrefs = vspecMap |> Map.map (fun _ v -> isByrefTy cenv.g v.Type, v) let envinner = if isMember then envinner else ExitFamilyRegion envinner + let vspecs = vs |> List.map (fun nm -> NameMap.find nm vspecMap) + + // Match up the arginfos with the generated arguments and apply any information extracted from the attributes + let envinner = + match envinner.eLambdaArgInfos with + | infos :: rest -> + if infos.Length = vspecs.Length then + (vspecs, infos) ||> List.iter2 (fun v argInfo -> + let inlineIfLambda = HasFSharpAttribute cenv.g cenv.g.attrib_InlineIfLambdaAttribute argInfo.Attribs + if inlineIfLambda then + v.SetInlineIfLambda()) + { envinner with eLambdaArgInfos = rest } + | [] -> envinner + let bodyExpr, tpenv = TcIteratedLambdas cenv false envinner resultTy takenNames tpenv bodyExpr // See bug 5758: Non-monotonicity in inference: need to ensure that parameters are never inferred to have byref type, instead it is always declared byrefs |> Map.iter (fun _ (orig, v) -> if not orig && isByrefTy cenv.g v.Type then errorR(Error(FSComp.SR.tcParameterInferredByref v.DisplayName, v.Range))) - mkMultiLambda m (List.map (fun nm -> NameMap.find nm vspecMap) vs) (bodyExpr, resultTy), tpenv - | e -> + + mkMultiLambda m vspecs (bodyExpr, resultTy), tpenv + + | e -> // Dive into the expression to check for syntax errors and suppress them if they show. conditionallySuppressErrorReporting (not isFirst && synExprContainsError e) (fun () -> //TcExprFlex cenv true true overallTy env tpenv e) @@ -6936,7 +6963,7 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr if isFSharpObjModelTy cenv.g overallTy then errorR(Error(FSComp.SR.tcTypeIsNotARecordTypeNeedConstructor(), mWholeExpr)) elif not (isRecdTy cenv.g overallTy) then errorR(Error(FSComp.SR.tcTypeIsNotARecordType(), mWholeExpr)) - let superTy, tpenv = + let superInitExprOpt , tpenv = match inherits, GetSuperTypeOfType cenv.g cenv.amap mWholeExpr overallTy with | Some (superTy, arg, m, _, _), Some realSuperTy -> // Constructor expression, with an explicit 'inheritedTys clause. Check the inherits clause. @@ -6955,9 +6982,9 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr let expr, tpenv = TcRecordConstruction cenv overallTy env tpenv optOrigExprInfo overallTy fldsList mWholeExpr let expr = - match superTy with + match superInitExprOpt with | _ when isStructTy cenv.g overallTy -> expr - | Some e -> mkCompGenSequential mWholeExpr e expr + | Some superInitExpr -> mkCompGenSequential mWholeExpr superInitExpr expr | None -> expr expr, tpenv @@ -7204,10 +7231,10 @@ and TcForEachExpr cenv overallTy env tpenv (pat, enumSynExpr, bodySynExpr, mWhol // Add the pattern match compilation let bodyExpr = let valsDefinedByMatching = ListSet.remove valEq elemVar vspecs - CompilePatternForMatch - cenv env enumSynExpr.Range pat.Range false IgnoreWithWarning (elemVar, [], None) - [TClause(pat, None, TTarget(valsDefinedByMatching, bodyExpr, DebugPointForTarget.Yes), mForLoopStart)] - enumElemTy + CompilePatternForMatch + cenv env enumSynExpr.Range pat.Range false IgnoreWithWarning (elemVar, [], None) + [TClause(pat, None, TTarget(valsDefinedByMatching, bodyExpr, DebugPointForTarget.Yes, None), mForLoopStart)] + enumElemTy overallTy // Apply the fixup to bind the elemVar if needed @@ -7267,8 +7294,7 @@ and TcQuotationExpr cenv overallTy env tpenv (_oper, raw, ast, isFromQueryExpres // We serialize the quoted expression to bytes in IlxGen after type inference etc. is complete. expr, tpenv - -/// When checking sequence of function applications, +/// When checking sequence of function applications, /// type applications and dot-notation projections, first extract known /// type information from the applications. /// @@ -9192,7 +9218,7 @@ and TcMatchClause cenv inputTy resultTy env isFirst tpenv (SynMatchClause(pat, o let pat', optWhenExpr', vspecs, envinner, tpenv = TcMatchPattern cenv inputTy env tpenv (pat, optWhenExpr) let resultEnv = if isFirst then envinner else { envinner with eContextInfo = ContextInfo.FollowingPatternMatchClause e.Range } let e', tpenv = TcExprThatCanBeCtorBody cenv resultTy resultEnv tpenv e - TClause(pat', optWhenExpr', TTarget(vspecs, e', spTgt), patm), tpenv + TClause(pat', optWhenExpr', TTarget(vspecs, e', spTgt, None), patm), tpenv and TcStaticOptimizationConstraint cenv env tpenv c = match c with @@ -9366,7 +9392,20 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt let argAndRetAttribs = ArgAndRetAttribs(argAttribs, retAttribs) - if HasFSharpAttribute cenv.g cenv.g.attrib_DefaultValueAttribute valAttribs then + // See RFC FS-1087, the 'Zero' method of a builder may have 'DefaultValueAttribute' indicating it should + // always be used for empty branches of if/then/else and others + let isZeroMethod = + match declKind, pat with + | ModuleOrMemberBinding, SynPat.Named(id, _, _, _) when id.idText = "Zero" -> + match memberFlagsOpt with + | Some memberFlags -> + match memberFlags.MemberKind with + | SynMemberKind.Member -> true + | _ -> false + | _ -> false + | _ -> false + + if HasFSharpAttribute cenv.g cenv.g.attrib_DefaultValueAttribute valAttribs && not isZeroMethod then errorR(Error(FSComp.SR.tcDefaultValueAttributeRequiresVal(), mBinding)) let isThreadStatic = isThreadOrContextStatic cenv.g valAttribs @@ -9460,6 +9499,10 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt conditionallySuppressErrorReporting atTopNonLambdaDefn (fun () -> + // Save the arginfos away to match them up in the lambda + let (PartialValReprInfo(argInfos, _)) = partialValReprInfo + let envinner = { envinner with eLambdaArgInfos = argInfos } + if isCtor then TcExprThatIsCtorBody (safeThisValOpt, safeInitInfo) cenv overallExprTy envinner tpenv rhsExpr else TcExprThatCantBeCtorBody cenv overallExprTy envinner tpenv rhsExpr) @@ -9808,7 +9851,7 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (synBinds, synBinds // Don't introduce temporary or 'let' for 'match against wild' or 'match against unit' | (TPat_wild _ | TPat_const (Const.Unit, _)) when not isUse && not isFixed && isNil generalizedTypars -> - let mkSequentialBind (tm, tmty) = (mkSequential DebugPointAtSequential.Both m rhsExpr tm, tmty) + let mkSequentialBind (tm, tmty) = (mkSequential DebugPointAtSequential.SuppressNeither m rhsExpr tm, tmty) (buildExpr >> mkSequentialBind, env, tpenv) | _ -> @@ -9859,7 +9902,7 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (synBinds, synBinds // Add the compilation of the pattern to the bodyExpr we get from mkCleanup let mkPatBind (bodyExpr, bodyExprTy) = let valsDefinedByMatching = ListSet.remove valEq patternInputTmp allValsDefinedByPattern - let clauses = [TClause(checkedPat2, None, TTarget(valsDefinedByMatching, bodyExpr, DebugPointForTarget.No), m)] + let clauses = [TClause(checkedPat2, None, TTarget(valsDefinedByMatching, bodyExpr, DebugPointForTarget.No, None), m)] let matchx = CompilePatternForMatch cenv env m m true ThrowIncompleteMatchException (patternInputTmp, generalizedTypars, Some rhsExpr) clauses tauTy bodyExprTy let matchx = if (DeclKind.ConvertToLinearBindings declKind) then LinearizeTopMatch cenv.g altActualParent matchx else matchx matchx, bodyExprTy diff --git a/src/fsharp/CheckExpressions.fsi b/src/fsharp/CheckExpressions.fsi index fa33a268406..7aa9e041747 100644 --- a/src/fsharp/CheckExpressions.fsi +++ b/src/fsharp/CheckExpressions.fsi @@ -98,6 +98,9 @@ type TcEnv = eCtorInfo: CtorInfo option eCallerMemberName: string option + + // Active arg infos in iterated lambdas , allowing us to determine the attributes of arguments + eLambdaArgInfos: ArgReprInfo list list } member DisplayEnv : DisplayEnv diff --git a/src/fsharp/CompilerDiagnostics.fs b/src/fsharp/CompilerDiagnostics.fs index bcbe770d69b..5dc0d50628d 100644 --- a/src/fsharp/CompilerDiagnostics.fs +++ b/src/fsharp/CompilerDiagnostics.fs @@ -374,7 +374,8 @@ let warningOn err level specificWarnOn = match n with | 1182 -> false // chkUnusedValue - off by default | 3180 -> false // abImplicitHeapAllocation - off by default - | _ -> level >= GetWarningLevel err + | 3517 -> false // optFailedToInlineSuggestedValue - off by default + | _ -> level >= GetWarningLevel err let SplitRelatedDiagnostics(err: PhasedDiagnostic) : PhasedDiagnostic * PhasedDiagnostic list = let ToPhased e = {Exception=e; Phase = err.Phase} diff --git a/src/fsharp/DetupleArgs.fs b/src/fsharp/DetupleArgs.fs index 609ab4c202f..6bd70e56bab 100644 --- a/src/fsharp/DetupleArgs.fs +++ b/src/fsharp/DetupleArgs.fs @@ -288,7 +288,7 @@ module GlobalUsageAnalysis = let context = [] recognise context origExpr - let targetIntercept exprF z = function TTarget(_argvs, body, _) -> Some (foldUnderLambda exprF z body) + let targetIntercept exprF z = function TTarget(_argvs, body, _, _) -> Some (foldUnderLambda exprF z body) let tmethodIntercept exprF z = function TObjExprMethod(_, _, _, _, e, _m) -> Some (foldUnderLambda exprF z e) {ExprFolder0 with @@ -300,7 +300,6 @@ module GlobalUsageAnalysis = tmethodIntercept = tmethodIntercept } - //------------------------------------------------------------------------- // GlobalUsageAnalysis - entry point //------------------------------------------------------------------------- @@ -310,7 +309,6 @@ module GlobalUsageAnalysis = let z = FoldImplFile folder z0 expr z - let internalError str = raise(Failure(str)) let mkLocalVal m name ty topValInfo = diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 4cc83b0aec1..5b45a4451fb 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1524,6 +1524,7 @@ featurePackageManagement,"package management" featureFromEndSlicing,"from-end slicing" featureFixedIndexSlice3d4d,"fixed-index slice 3d/4d" featureAndBang,"applicative computation expressions" +featureResumableStateMachines,"resumable state machines" featureNullableOptionalInterop,"nullable optional interop" featureDefaultInterfaceMemberConsumption,"default interface member consumption" featureStringInterpolation,"string interpolation" @@ -1565,4 +1566,26 @@ forFormatInvalidForInterpolated4,"Interpolated strings used as type IFormattable 3390,xmlDocMissingParameter,"This XML comment is incomplete: no documentation for parameter '%s'" 3391,tcLiteralAttributeCannotUseActivePattern,"A [] declaration cannot use an active pattern for its identifier" 3392,containerDeprecated,"The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead." -3393,containerSigningUnsupportedOnThisPlatform,"Key container signing is not supported on this platform." \ No newline at end of file +3393,containerSigningUnsupportedOnThisPlatform,"Key container signing is not supported on this platform." +3401,ilxgenInvalidConstructInStateMachineDuringCodegen,"The resumable code construct '%s' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code." +3402,tcInvalidResumableConstruct,"The construct '%s' may only be used in valid resumable code." +3501,tcResumableCodeFunctionMustBeInline,"Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline'" +3501,tcResumableCodeArgMustHaveRightName,"Invalid resumable code. Resumable code parameter must have name beginning with '__expand'" +3501,tcResumableCodeArgMustHaveRightKind,"Invalid resumable code. A resumable code parameter must be of delegate or function type" +3501,tcResumableCodeContainsLetRec,"Invalid resumable code. A 'let rec' occured in the resumable code specification" +3510,tcResumableCodeNotSupported,"Using resumable code or resumable state machines requires /langversion:preview" +3511,reprStateMachineNotCompilable,"This state machine is not statically compilable. %s. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning." +3512,reprStateMachineNotCompilableNoAlternative,"This state machine is not statically compilable and no alternative is available. %s. Use an 'if __useResumableCode then else ' to give an alternative." +3513,tcResumableCodeInvocation,"Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code." +reprResumableCodeInvokeNotReduced,"A resumable code invocation at '%s' could not be reduced" +reprResumableCodeContainsLetRec,"A 'let rec' occured in the resumable code specification" +reprResumableCodeContainsDynamicResumeAtInBody,"A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method" +reprResumableCodeContainsResumptionInTryFinally,"A try/finally may not contain resumption points" +reprResumableCodeContainsResumptionInHandlerOrFilter,"The 'with' block of a try/with may not contain resumption points" +reprResumableCodeContainsFastIntegerForLoop,"A fast integer for loop may not contain resumption points" +reprResumableCodeValueHasNoDefinition,"The resumable code value(s) '%s' does not have a definition" +reprResumableCodeDefinitionWasGeneric,"A delegate or function producing resumable code in a state machine has type parameters" +reprStateMachineInvalidForm,"The state machine has an unexpected form" +3517,optFailedToInlineSuggestedValue,"The value '%s' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only." +3518,implMissingInlineIfLambda,"The 'InlineIfLambda' attribute is present in the signature but not the implementation." +3519,tcInlineIfLambdaUsedOnNonInlineFunctionOrMethod,"The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type." diff --git a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index ff2d0cd0770..6f40101419c 100644 --- a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -502,7 +502,7 @@ TypedTree\CompilerGlobalState.fs - TypedTree\TypedTree.fs + TypedTree\TypedTreeBasics.fs TypedTree\TypedTreeBasics.fsi @@ -675,6 +675,12 @@ Optimize\LowerCallsAndSeqs.fs + + Optimize\LowerStateMachines.fsi + + + Optimize\LowerStateMachines.fs + Optimize\autobox.fsi diff --git a/src/fsharp/FSharp.Compiler.Service/StandardError.txt b/src/fsharp/FSharp.Compiler.Service/StandardError.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/fsharp/FSharp.Compiler.Service/StandardOutput.txt b/src/fsharp/FSharp.Compiler.Service/StandardOutput.txt new file mode 100644 index 00000000000..307a3493b91 --- /dev/null +++ b/src/fsharp/FSharp.Compiler.Service/StandardOutput.txt @@ -0,0 +1 @@ +5.0.104 diff --git a/src/fsharp/FSharp.Core/FSharp.Core.fsproj b/src/fsharp/FSharp.Core/FSharp.Core.fsproj index f7267fe0d84..4fafe661c48 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.fsproj +++ b/src/fsharp/FSharp.Core/FSharp.Core.fsproj @@ -1,16 +1,30 @@ - + Library - netstandard2.0 + netstandard2.1;netstandard2.0 $(NoWarn);45;55;62;75;1204 true $(DefineConstants);FSHARP_CORE BUILDING_WITH_LKG;$(DefineConstants) - $(OtherFlags) --warnon:3218 --warnon:1182 --warnon:3390 --compiling-fslib --compiling-fslib-40 --maxerrors:100 --extraoptimizationloops:1 --nowarn:57 - true + + $(OtherFlags) --warnon:3218 + + $(OtherFlags) --warnon:1182 + + $(OtherFlags) --warnon:3390 + + $(OtherFlags) --nowarn:57 + + + $(OtherFlags) --nowarn:3511 --nowarn:3513 + $(OtherFlags) --compiling-fslib --compiling-fslib-40 --maxerrors:100 --extraoptimizationloops:1 + + preview + + true true true @@ -162,12 +176,24 @@ Control/event.fs + + Control/resumable.fsi + + + Control/resumable.fs + Control/async.fsi Control/async.fs + + Control/tasks.fsi + + + Control/tasks.fs + Control/eventmodule.fsi diff --git a/src/fsharp/FSharp.Core/FSharp.Core.nuspec b/src/fsharp/FSharp.Core/FSharp.Core.nuspec index f2cd1cf86b0..4efa4c5c661 100644 --- a/src/fsharp/FSharp.Core/FSharp.Core.nuspec +++ b/src/fsharp/FSharp.Core/FSharp.Core.nuspec @@ -5,6 +5,7 @@ en-US + @@ -19,5 +20,12 @@ + + + + + + + diff --git a/src/fsharp/FSharp.Core/array.fs b/src/fsharp/FSharp.Core/array.fs index d66792beec3..407ac4aff78 100644 --- a/src/fsharp/FSharp.Core/array.fs +++ b/src/fsharp/FSharp.Core/array.fs @@ -238,7 +238,7 @@ namespace Microsoft.FSharp.Collections res [] - let inline iter action (array: 'T[]) = + let inline iter ([] action) (array: 'T[]) = checkNonNull "array" array for i = 0 to array.Length-1 do action array.[i] @@ -258,7 +258,7 @@ namespace Microsoft.FSharp.Collections Microsoft.FSharp.Primitives.Basics.Array.subUnchecked 0 i temp [] - let inline map (mapping: 'T -> 'U) (array: 'T[]) = + let inline map ([] mapping: 'T -> 'U) (array: 'T[]) = checkNonNull "array" array let res: 'U[] = Microsoft.FSharp.Primitives.Basics.Array.zeroCreateUnchecked array.Length for i = 0 to res.Length-1 do @@ -1110,7 +1110,7 @@ namespace Microsoft.FSharp.Collections acc [] - let inline minBy projection (array: _[]) = + let inline minBy ([] projection) (array: _[]) = checkNonNull "array" array if array.Length = 0 then invalidArg "array" LanguagePrimitives.ErrorStrings.InputArrayEmptyString let mutable accv = array.[0] @@ -1167,7 +1167,7 @@ namespace Microsoft.FSharp.Collections LanguagePrimitives.DivideByInt< ^U> acc array.Length [] - let inline compareWith (comparer: 'T -> 'T -> int) (array1: 'T[]) (array2: 'T[]) = + let inline compareWith ([] comparer: 'T -> 'T -> int) (array1: 'T[]) (array2: 'T[]) = checkNonNull "array1" array1 checkNonNull "array2" array2 diff --git a/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs b/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs index 7d05c29b497..5fd4e32b29e 100644 --- a/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs +++ b/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs @@ -268,6 +268,11 @@ module ExtraTopLevelOperators = [] [] [] + #if !BUILDING_WITH_LKG && !BUILD_FROM_SOURCE + [] + [] + [] + #endif [] [] do() diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 319481c6814..02b11b4bb42 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -108,7 +108,7 @@ namespace Microsoft.FSharp.Core inherit System.Attribute() member x.Value = value - [] + [] [] type DefaultValueAttribute(check:bool) = inherit System.Attribute() @@ -261,6 +261,11 @@ namespace Microsoft.FSharp.Core member x.Message = message + [] + [] + type InlineIfLambdaAttribute() = + inherit System.Attribute() + [] [] type CompilationArgumentCountsAttribute(counts:int[]) = diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index 2ed374eb5ce..baa9a5127b2 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -520,7 +520,7 @@ namespace Microsoft.FSharp.Core /// /// /// Attributes - [] + [] [] type DefaultValueAttribute = inherit Attribute @@ -773,6 +773,22 @@ namespace Microsoft.FSharp.Core /// Indicates the warning message to be emitted when F# source code uses this construct member Message: string + /// Adding this attribute to a parameter of function type indicates that, if the overall function or method is inlined and the parameter is + /// determined to be a known lambda, then this function should be statically inlined throughout the body of the function of method. + /// + /// If the function parameter is called multiple times in the implementation of the function or method this attribute may cause code explosion and slow compilation times. + /// + /// Attributes + [] + [] + [] + type InlineIfLambdaAttribute = + inherit Attribute + + /// Creates an instance of the attribute + /// InlineIfLambdaAttribute + new : unit -> InlineIfLambdaAttribute + /// This attribute is generated automatically by the F# compiler to tag functions and members /// that accept a partial application of some of their arguments and return a residual function. /// diff --git a/src/fsharp/FSharp.Core/resumable.fs b/src/fsharp/FSharp.Core/resumable.fs new file mode 100644 index 00000000000..caddd62fe91 --- /dev/null +++ b/src/fsharp/FSharp.Core/resumable.fs @@ -0,0 +1,375 @@ +// Original notice: +// To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights +// to this software to the public domain worldwide. This software is distributed without any warranty. +// +// Updates: +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +#nowarn "9" +#nowarn "51" +namespace Microsoft.FSharp.Core.CompilerServices + +#if !BUILDING_WITH_LKG && !BUILD_FROM_SOURCE +open System +open System.Runtime.CompilerServices +open Microsoft.FSharp.Core +open Microsoft.FSharp.Core +open Microsoft.FSharp.Core.Printf +open Microsoft.FSharp.Core.CompilerServices +open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators +open Microsoft.FSharp.Control +open Microsoft.FSharp.Collections + +type IResumableStateMachine<'Data> = + abstract ResumptionPoint: int + abstract Data: 'Data with get, set + +/// Acts as a template for struct state machines introduced by __stateMachine, and also as a reflective implementation +[] +type ResumableStateMachine<'Data> = + + [] + val mutable Data: 'Data + + [] + val mutable ResumptionPoint: int + + /// Represents the delegated runtime continuation of a resumable state machine created dynamically + [] + val mutable ResumptionDynamicInfo: ResumptionDynamicInfo<'Data> + + interface IResumableStateMachine<'Data> with + member sm.ResumptionPoint = sm.ResumptionPoint + member sm.Data with get() = sm.Data and set v = sm.Data <- v + + interface IAsyncStateMachine with + + // Used for dynamic execution. For "__stateMachine" it is replaced. + member sm.MoveNext() = + sm.ResumptionDynamicInfo.MoveNext(&sm) + + // Used when dynamic execution. For "__stateMachine" it is replaced. + member sm.SetStateMachine(state) = + sm.ResumptionDynamicInfo.SetStateMachine(&sm, state) + +and ResumptionFunc<'Data> = delegate of byref> -> bool + +and [] + ResumptionDynamicInfo<'Data>(initial: ResumptionFunc<'Data>) = + member val ResumptionFunc: ResumptionFunc<'Data> = initial with get, set + member val ResumptionData: obj = null with get, set + abstract MoveNext: machine: byref> -> unit + abstract SetStateMachine: machine: byref> * machineState: IAsyncStateMachine -> unit + +type ResumableCode<'Data, 'T> = delegate of byref> -> bool + +/// Defines the implementation of the MoveNext method for a struct state machine. +[] +type MoveNextMethodImpl<'Data> = delegate of byref> -> unit + +/// Defines the implementation of the SetStateMachine method for a struct state machine. +[] +type SetStateMachineMethodImpl<'Data> = delegate of byref> * IAsyncStateMachine -> unit + +/// Defines the implementation of the code reun after the creation of a struct state machine. +[] +type AfterCode<'Data, 'Result> = delegate of byref> -> 'Result + +[] +module StateMachineHelpers = + + /// Statically determines whether resumable code is being used + [] + let __useResumableCode<'T> : bool = false + + [] + let __resumableEntry () : int option = + failwith "__resumableEntry should always be guarded by __useResumableCode and only used in valid state machine implementations" + + [] + let __resumeAt<'T> (programLabel: int) : 'T = + ignore programLabel + failwith "__resumeAt should always be guarded by __useResumableCode and only used in valid state machine implementations" + + [] + let __stateMachine<'Data, 'Result> + (moveNextMethod: MoveNextMethodImpl<'Data>) + (setStateMachineMethod: SetStateMachineMethodImpl<'Data>) + (afterCode: AfterCode<'Data, 'Result>): 'Result = + ignore moveNextMethod + ignore setStateMachineMethod + ignore afterCode + failwith "__stateMachine should always be guarded by __useResumableCode and only used in valid state machine implementations" + +module ResumableCode = + + let inline SetResumptionFunc (sm: byref>) f = + sm.ResumptionDynamicInfo.ResumptionFunc <- f + + let inline GetResumptionFunc (sm: byref>) = + sm.ResumptionDynamicInfo.ResumptionFunc + + let inline Delay(f : unit -> ResumableCode<'Data, 'T>) : ResumableCode<'Data, 'T> = + ResumableCode<'Data, 'T>(fun sm -> (f()).Invoke(&sm)) + + /// Used to represent no-ops like the implicit empty "else" branch of an "if" expression. + let inline Zero() : ResumableCode<'Data, unit> = + ResumableCode<'Data, unit>(fun sm -> true) + + /// Chains together a step with its following step. + /// Note that this requires that the first step has no result. + /// This prevents constructs like `task { return 1; return 2; }`. + let CombineDynamic(sm: byref>, code1: ResumableCode<'Data, unit>, code2: ResumableCode<'Data, 'T>) : bool = + if code1.Invoke(&sm) then + code2.Invoke(&sm) + else + let rec resume (mf: ResumptionFunc<'Data>) = + ResumptionFunc<'Data>(fun sm -> + if mf.Invoke(&sm) then + code2.Invoke(&sm) + else + sm.ResumptionDynamicInfo.ResumptionFunc <- (resume (GetResumptionFunc &sm)) + false) + + sm.ResumptionDynamicInfo.ResumptionFunc <- (resume (GetResumptionFunc &sm)) + false + + /// Chains together a step with its following step. + /// Note that this requires that the first step has no result. + /// This prevents constructs like `task { return 1; return 2; }`. + let inline Combine(code1: ResumableCode<'Data, unit>, code2: ResumableCode<'Data, 'T>) : ResumableCode<'Data, 'T> = + ResumableCode<'Data, 'T>(fun sm -> + if __useResumableCode then + //-- RESUMABLE CODE START + // NOTE: The code for code1 may contain await points! Resuming may branch directly + // into this code! + let __stack_fin = code1.Invoke(&sm) + if __stack_fin then + code2.Invoke(&sm) + else + false + //-- RESUMABLE CODE END + else + CombineDynamic(&sm, code1, code2)) + + let rec WhileDynamic (sm: byref>, condition: unit -> bool, body: ResumableCode<'Data,unit>) : bool = + if condition() then + if body.Invoke (&sm) then + WhileDynamic (&sm, condition, body) + else + let rf = GetResumptionFunc &sm + sm.ResumptionDynamicInfo.ResumptionFunc <- (ResumptionFunc<'Data>(fun sm -> WhileBodyDynamicAux(&sm, condition, body, rf))) + false + else + true + and WhileBodyDynamicAux (sm: byref>, condition: unit -> bool, body: ResumableCode<'Data,unit>, rf: ResumptionFunc<_>) : bool = + if rf.Invoke (&sm) then + WhileDynamic (&sm, condition, body) + else + let rf = GetResumptionFunc &sm + sm.ResumptionDynamicInfo.ResumptionFunc <- (ResumptionFunc<'Data>(fun sm -> WhileBodyDynamicAux(&sm, condition, body, rf))) + false + + /// Builds a step that executes the body while the condition predicate is true. + let inline While ([] condition : unit -> bool, body : ResumableCode<'Data, unit>) : ResumableCode<'Data, unit> = + ResumableCode<'Data, unit>(fun sm -> + if __useResumableCode then + //-- RESUMABLE CODE START + let mutable __stack_go = true + while __stack_go && condition() do + // NOTE: The body of the state machine code for 'while' may contain await points, so resuming + // the code will branch directly into the expanded 'body', branching directly into the while loop + let __stack_body_fin = body.Invoke(&sm) + // If the body completed, we go back around the loop (__stack_go = true) + // If the body yielded, we yield (__stack_go = false) + __stack_go <- __stack_body_fin + __stack_go + //-- RESUMABLE CODE END + else + WhileDynamic(&sm, condition, body)) + + let rec TryWithDynamic (sm: byref>, body: ResumableCode<'Data, 'T>, handler: exn -> ResumableCode<'Data, 'T>) : bool = + try + if body.Invoke(&sm) then + true + else + let rf = GetResumptionFunc &sm + sm.ResumptionDynamicInfo.ResumptionFunc <- (ResumptionFunc<'Data>(fun sm -> TryWithDynamic(&sm, ResumableCode<'Data,'T>(fun sm -> rf.Invoke(&sm)), handler))) + false + with exn -> + (handler exn).Invoke(&sm) + + /// Wraps a step in a try/with. This catches exceptions both in the evaluation of the function + /// to retrieve the step, and in the continuation of the step (if any). + let inline TryWith (body: ResumableCode<'Data, 'T>, catch: exn -> ResumableCode<'Data, 'T>) : ResumableCode<'Data, 'T> = + ResumableCode<'Data, 'T>(fun sm -> + if __useResumableCode then + //-- RESUMABLE CODE START + let mutable __stack_fin = false + let mutable __stack_caught = false + let mutable __stack_savedExn = Unchecked.defaultof<_> + // This is a meaningless assignment but ensures a debug point gets laid down + // at the 'try' in the try/with for code as we enter into the handler. + __stack_fin <- __stack_fin || __stack_fin + try + // The try block may contain await points. + let __stack_body_fin = body.Invoke(&sm) + // If we make it to the assignment we prove we've made a step + __stack_fin <- __stack_body_fin + with exn -> + // Note, remarkExpr in the F# compiler detects this pattern as the code + // is inlined and elides the debug sequence point on the code. This is because the inlining will associate + // the sequence point with the 'try' of the TryFinally because that is the range + // given for the whole expression + // task.TryWith(....) + // If you change this code you should check debug sequence points and the generated + // code tests for try/with in tasks. + __stack_caught <- true + __stack_savedExn <- exn + + if __stack_caught then + // Place the catch code outside the catch block + (catch __stack_savedExn).Invoke(&sm) + else + __stack_fin + //-- RESUMABLE CODE END + + else + TryWithDynamic(&sm, body, catch)) + + let rec TryFinallyCompensateDynamic (sm: byref>, mf: ResumptionFunc<'Data>, savedExn: exn option) : bool = + let mutable fin = false + fin <- mf.Invoke(&sm) + if fin then + // reraise at the end of the finally block + match savedExn with + | None -> true + | Some exn -> raise exn + else + let rf = GetResumptionFunc &sm + sm.ResumptionDynamicInfo.ResumptionFunc <- (ResumptionFunc<'Data>(fun sm -> TryFinallyCompensateDynamic(&sm, rf, savedExn))) + false + + let rec TryFinallyAsyncDynamic (sm: byref>, body: ResumableCode<'Data, 'T>, compensation: ResumableCode<'Data,unit>) : bool = + let mutable fin = false + let mutable savedExn = None + try + fin <- body.Invoke(&sm) + with exn -> + savedExn <- Some exn + fin <- true + if fin then + TryFinallyCompensateDynamic(&sm, ResumptionFunc<'Data>(fun sm -> compensation.Invoke(&sm)), savedExn) + else + let rf = GetResumptionFunc &sm + sm.ResumptionDynamicInfo.ResumptionFunc <- (ResumptionFunc<'Data>(fun sm -> TryFinallyAsyncDynamic(&sm, ResumableCode<'Data,'T>(fun sm -> rf.Invoke(&sm)), compensation))) + false + + /// Wraps a step in a try/finally. This catches exceptions both in the evaluation of the function + /// to retrieve the step, and in the continuation of the step (if any). + let inline TryFinally (body: ResumableCode<'Data, 'T>, compensation: ResumableCode<'Data,unit>) = + ResumableCode<'Data, 'T>(fun sm -> + if __useResumableCode then + //-- RESUMABLE CODE START + let mutable __stack_fin = false + // This is a meaningless assignment but ensures a debug point gets laid down + // at the 'try' in the try/finally. The 'try' is used as the range for the + // F# computation expression desugaring to 'TryFinally' and this range in turn gets applied + // to inlined code. + __stack_fin <- __stack_fin || __stack_fin + try + let __stack_body_fin = body.Invoke(&sm) + // If we make it to the assignment we prove we've made a step, an early 'ret' exit out of the try/with + // may skip this step. + __stack_fin <- __stack_body_fin + with _exn -> + // Note, remarkExpr in the F# compiler detects this pattern as the code + // is inlined and elides the debug sequence point on either the 'compensation' + // 'reraise' statement for the code. This is because the inlining will associate + // the sequence point with the 'try' of the TryFinally because that is the range + // given for the whole expression + // task.TryFinally(....) + // If you change this code you should check debug sequence points and the generated + // code tests for try/finally in tasks. + let __stack_ignore = compensation.Invoke(&sm) + reraise() + + if __stack_fin then + let __stack_ignore = compensation.Invoke(&sm) + () + __stack_fin + //-- RESUMABLE CODE END + else + TryFinallyAsyncDynamic(&sm, body, ResumableCode<_,_>(fun sm -> compensation.Invoke(&sm)))) + + /// Wraps a step in a try/finally. This catches exceptions both in the evaluation of the function + /// to retrieve the step, and in the continuation of the step (if any). + let inline TryFinallyAsync (body: ResumableCode<'Data, 'T>, compensation: ResumableCode<'Data,unit>) : ResumableCode<'Data, 'T> = + ResumableCode<'Data, 'T>(fun sm -> + if __useResumableCode then + //-- RESUMABLE CODE START + let mutable __stack_fin = false + let mutable savedExn = None + // This is a meaningless assignment but ensures a debug point gets laid down + // at the 'try' in the try/finally. The 'try' is used as the range for the + // F# computation expression desugaring to 'TryFinally' and this range in turn gets applied + // to inlined code. + __stack_fin <- __stack_fin || __stack_fin + try + let __stack_body_fin = body.Invoke(&sm) + // If we make it to the assignment we prove we've made a step, an early 'ret' exit out of the try/with + // may skip this step. + __stack_fin <- __stack_body_fin + with exn -> + savedExn <- Some exn + __stack_fin <- true + + if __stack_fin then + let __stack_compensation_fin = compensation.Invoke(&sm) + __stack_fin <- __stack_compensation_fin + if __stack_fin then + match savedExn with + | None -> () + | Some exn -> raise exn + __stack_fin + //-- RESUMABLE CODE END + else + TryFinallyAsyncDynamic(&sm, body, compensation)) + + let inline Using (resource : 'Resource, body : 'Resource -> ResumableCode<'Data, 'T>) : ResumableCode<'Data, 'T> when 'Resource :> IDisposable = + // A using statement is just a try/finally with the finally block disposing if non-null. + TryFinally( + ResumableCode<'Data, 'T>(fun sm -> (body resource).Invoke(&sm)), + ResumableCode<'Data,unit>(fun sm -> + if not (isNull (box resource)) then + resource.Dispose() + true)) + + let inline For (sequence : seq<'T>, body : 'T -> ResumableCode<'Data, unit>) : ResumableCode<'Data, unit> = + // A for loop is just a using statement on the sequence's enumerator... + Using (sequence.GetEnumerator(), + // ... and its body is a while loop that advances the enumerator and runs the body on each element. + (fun e -> While((fun () -> e.MoveNext()), ResumableCode<'Data, unit>(fun sm -> (body e.Current).Invoke(&sm))))) + + let YieldDynamic (sm: byref>) : bool = + let cont = ResumptionFunc<'Data>(fun _sm -> true) + sm.ResumptionDynamicInfo.ResumptionFunc <- cont + false + + let inline Yield () : ResumableCode<'Data, unit> = + ResumableCode<'Data, unit>(fun sm -> + if __useResumableCode then + //-- RESUMABLE CODE START + match __resumableEntry() with + | Some contID -> + sm.ResumptionPoint <- contID + //if verbose then printfn $"[{sm.Id}] Yield: returning false to indicate yield, contID = {contID}" + false + | None -> + //if verbose then printfn $"[{sm.Id}] Yield: returning true to indicate post-yield" + true + //-- RESUMABLE CODE END + else + YieldDynamic(&sm)) + +#endif diff --git a/src/fsharp/FSharp.Core/resumable.fsi b/src/fsharp/FSharp.Core/resumable.fsi new file mode 100644 index 00000000000..a7b4ff17ef1 --- /dev/null +++ b/src/fsharp/FSharp.Core/resumable.fsi @@ -0,0 +1,204 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.FSharp.Core.CompilerServices + +#if !BUILDING_WITH_LKG && !BUILD_FROM_SOURCE +open Microsoft.FSharp.Collections +open Microsoft.FSharp.Core +open System +open System.Runtime.CompilerServices + +/// Acts as a template for struct state machines introduced by __stateMachine, and also as a reflective implementation +[] +[] +type ResumableStateMachine<'Data> = + + /// When statically compiled, holds the data for the state machine + [] + val mutable Data: 'Data + + /// When statically compiled, holds the continuation goto-label further execution of the state machine + [] + val mutable ResumptionPoint: int + + /// Represents the delegated runtime continuation for a resumable state machine created dynamically + /// This field is removed from state machines generated using '__stateMachine'. Resumable code + /// used in state machines which accesses this field will raise a runtime exception. + [] + val mutable ResumptionDynamicInfo: ResumptionDynamicInfo<'Data> + + interface IResumableStateMachine<'Data> + + interface IAsyncStateMachine + +and + [] + IResumableStateMachine<'Data> = + /// Get the resumption point of the state machine + abstract ResumptionPoint: int + + /// Copy-out or copy-in the data of the state machine + abstract Data: 'Data with get, set + +/// Represents the delegated runtime continuation of a resumable state machine created dynamically +and + [] + ResumptionDynamicInfo<'Data> = + + /// Create dynamic information for a state machine + new: initial: ResumptionFunc<'Data> -> ResumptionDynamicInfo<'Data> + + /// The continuation of the state machine + member ResumptionFunc: ResumptionFunc<'Data> with get, set + + /// Additional data associated with the state machine + member ResumptionData: obj with get, set + + /// Executes the MoveNext implementation of the state machine + abstract MoveNext: machine: byref> -> unit + + /// Executes the SetStateMachine implementation of the state machine + abstract SetStateMachine: machine: byref> * machineState: IAsyncStateMachine -> unit + +/// Represents the runtime continuation of a resumable state machine created dynamically +and [] + ResumptionFunc<'Data> = delegate of byref> -> bool + +/// A special compiler-recognised delegate type for specifying blocks of resumable code +/// with access to the state machine. +[] +type ResumableCode<'Data, 'T> = delegate of byref> -> bool + +/// Contains functions for composing resumable code blocks +[] +[] +module ResumableCode = + + /// Sequences one section of resumable code after another + [] + val inline Combine: code1: ResumableCode<'Data, unit> * code2: ResumableCode<'Data, 'T> -> ResumableCode<'Data, 'T> + + /// Creates resumable code whose definition is a delayed function + [] + val inline Delay: f: (unit -> ResumableCode<'Data, 'T>) -> ResumableCode<'Data, 'T> + + /// Specifies resumable code which iterates an input sequence + [] + val inline For: sequence: seq<'T> * body: ('T -> ResumableCode<'Data, unit>) -> ResumableCode<'Data, unit> + + /// Specifies resumable code which iterates yields + [] + val inline Yield: unit -> ResumableCode<'Data, unit> + + /// Specifies resumable code which executes with try/finally semantics + [] + val inline TryFinally: body: ResumableCode<'Data, 'T> * compensation: ResumableCode<'Data,unit> -> ResumableCode<'Data, 'T> + + /// Specifies resumable code which executes with try/finally semantics + [] + val inline TryFinallyAsync: body: ResumableCode<'Data, 'T> * compensation: ResumableCode<'Data,unit> -> ResumableCode<'Data, 'T> + + /// Specifies resumable code which executes with try/with semantics + [] + val inline TryWith: body: ResumableCode<'Data, 'T> * catch: (exn -> ResumableCode<'Data, 'T>) -> ResumableCode<'Data, 'T> + + /// Specifies resumable code which executes with 'use' semantics + [] + val inline Using: resource: 'Resource * body: ('Resource -> ResumableCode<'Data, 'T>) -> ResumableCode<'Data, 'T> when 'Resource :> IDisposable + + /// Specifies resumable code which executes a loop + [] + val inline While: [] condition: (unit -> bool) * body: ResumableCode<'Data, unit> -> ResumableCode<'Data, unit> + + /// Specifies resumable code which does nothing + [] + val inline Zero: unit -> ResumableCode<'Data, unit> + + /// The dynamic implementation of the corresponding operation. This operation should not be used directly. + [] + val CombineDynamic: sm: byref> * code1: ResumableCode<'Data, unit> * code2: ResumableCode<'Data, 'T> -> bool + + /// The dynamic implementation of the corresponding operation. This operation should not be used directly. + [] + val WhileDynamic: sm: byref> * condition: (unit -> bool) * body: ResumableCode<'Data, unit> -> bool + + /// The dynamic implementation of the corresponding operation. This operation should not be used directly. + [] + val TryFinallyAsyncDynamic: sm: byref> * body: ResumableCode<'Data, 'T> * compensation: ResumableCode<'Data,unit> -> bool + + /// The dynamic implementation of the corresponding operation. This operation should not be used directly. + [] + val TryWithDynamic: sm: byref> * body: ResumableCode<'Data, 'T> * handler: (exn -> ResumableCode<'Data, 'T>) -> bool + + /// The dynamic implementation of the corresponding operation. This operation should not be used directly. + [] + val YieldDynamic: sm: byref> -> bool + +/// Defines the implementation of the MoveNext method for a struct state machine. +[] +type MoveNextMethodImpl<'Data> = delegate of byref> -> unit + +/// Defines the implementation of the SetStateMachine method for a struct state machine. +[] +type SetStateMachineMethodImpl<'Data> = delegate of byref> * IAsyncStateMachine -> unit + +/// Defines the implementation of the code run after the creation of a struct state machine. +[] +type AfterCode<'Data, 'Result> = delegate of byref> -> 'Result + +/// Contains compiler intrinsics related to the definition of state machines. +[] +module StateMachineHelpers = + + /// + /// When used in a conditional, statically determines whether the 'then' branch + /// represents valid resumable code and provides an alternative implementation + /// if not. + /// + [] + [] + val __useResumableCode<'T> : bool + + /// + /// Indicates a resumption point within resumable code + /// + [] + [] + val __resumableEntry: unit -> int option + + /// + /// Indicates to jump to a resumption point within resumable code. + /// This may be the first statement in a MoveNextMethodImpl. + /// The integer must be a valid resumption point within this resumable code. + /// + /// + [] + [] + val __resumeAt : programLabel: int -> 'T + + /// + /// Statically generates a closure struct type based on ResumableStateMachine, + /// At runtime an instance of the new struct type is populated and 'afterMethod' is called + /// to consume it. + /// + /// + /// + /// At compile-time, the ResumableStateMachine type guides the generation of a new struct type by the F# compiler + /// with closure-capture fields in a way similar to an object expression. + /// Any mention of the ResumableStateMachine type in any the 'methods' is rewritten to this + /// fresh struct type. The 'methods' are used to implement the interfaces on ResumableStateMachine and are also rewritten. + /// The 'after' method is then executed and must eliminate the ResumableStateMachine. For example, + /// its return type must not include ResumableStateMachine. + /// + /// Gives the implementation of the MoveNext method on IAsyncStateMachine. + /// Gives the implementation of the SetStateMachine method on IAsyncStateMachine. + /// Gives code to execute after the generation of the state machine and to produce the final result. + [] + [] + val __stateMachine<'Data, 'Result> : + moveNextMethod: MoveNextMethodImpl<'Data> -> + setStateMachineMethod: SetStateMachineMethodImpl<'Data> -> + afterCode: AfterCode<'Data, 'Result> + -> 'Result + +#endif diff --git a/src/fsharp/FSharp.Core/seqcore.fs b/src/fsharp/FSharp.Core/seqcore.fs index 5a6e8142960..d4fa9b99de3 100644 --- a/src/fsharp/FSharp.Core/seqcore.fs +++ b/src/fsharp/FSharp.Core/seqcore.fs @@ -147,6 +147,7 @@ namespace Microsoft.FSharp.Core.CompilerServices open Microsoft.FSharp.Primitives.Basics open System.Collections open System.Collections.Generic + open System.Runtime.CompilerServices module RuntimeHelpers = diff --git a/src/fsharp/FSharp.Core/seqcore.fsi b/src/fsharp/FSharp.Core/seqcore.fsi index 9a0d9bd1055..cce9b5dbb3e 100644 --- a/src/fsharp/FSharp.Core/seqcore.fsi +++ b/src/fsharp/FSharp.Core/seqcore.fsi @@ -60,9 +60,10 @@ namespace Microsoft.FSharp.Core.CompilerServices open System open System.Collections open System.Collections.Generic + open System.Runtime.CompilerServices open Microsoft.FSharp.Core open Microsoft.FSharp.Collections - + [] /// A group of functions used as part of the compiled representation of F# sequence expressions. module RuntimeHelpers = @@ -128,20 +129,25 @@ namespace Microsoft.FSharp.Core.CompilerServices /// /// A new sequence generator for the expression. new : unit -> GeneratedSequenceBase<'T> + /// The F# compiler emits implementations of this type for compiled sequence expressions. /// /// A new enumerator for the sequence. abstract GetFreshEnumerator : unit -> IEnumerator<'T> + /// The F# compiler emits implementations of this type for compiled sequence expressions. /// /// A reference to the sequence. /// /// A 0, 1, and 2 respectively indicate Stop, Yield, and Goto conditions for the sequence generator. abstract GenerateNext : result:byref> -> int + /// The F# compiler emits implementations of this type for compiled sequence expressions. abstract Close: unit -> unit + /// The F# compiler emits implementations of this type for compiled sequence expressions. abstract CheckClose: bool + /// The F# compiler emits implementations of this type for compiled sequence expressions. abstract LastGenerated : 'T interface IEnumerable<'T> diff --git a/src/fsharp/FSharp.Core/tasks.fs b/src/fsharp/FSharp.Core/tasks.fs new file mode 100644 index 00000000000..e0032a24aaa --- /dev/null +++ b/src/fsharp/FSharp.Core/tasks.fs @@ -0,0 +1,384 @@ +// Task builder for F# that compiles to allocation-free paths for synchronous code. +// +// Originally written in 2016 by Robert Peele (humbobst@gmail.com) +// New operator-based overload resolution for F# 4.0 compatibility by Gustavo Leon in 2018. +// Revised for insertion into FSHarp.Core by Microsoft, 2019. +// +// Original notice: +// To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights +// to this software to the public domain worldwide. This software is distributed without any warranty. +// +// Updates: +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.FSharp.Control + + #if !BUILDING_WITH_LKG && !BUILD_FROM_SOURCE + open System + open System.Runtime.CompilerServices + open System.Threading + open System.Threading.Tasks + open Microsoft.FSharp.Core + open Microsoft.FSharp.Core.CompilerServices + open Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers + open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + open Microsoft.FSharp.Control + open Microsoft.FSharp.Collections + + /// The extra data stored in ResumableStateMachine for tasks + [] + type TaskStateMachineData<'T> = + + [] + val mutable Result : 'T + + [] + val mutable MethodBuilder : AsyncTaskMethodBuilder<'T> + + and TaskStateMachine<'TOverall> = ResumableStateMachine> + and TaskResumptionFunc<'TOverall> = ResumptionFunc> + and TaskResumptionDynamicInfo<'TOverall> = ResumptionDynamicInfo> + and TaskCode<'TOverall, 'T> = ResumableCode, 'T> + + type TaskBuilderBase() = + + member inline _.Delay(f : unit -> TaskCode<'TOverall, 'T>) : TaskCode<'TOverall, 'T> = + TaskCode<'TOverall, 'T>(fun sm -> (f()).Invoke(&sm)) + + /// Used to represent no-ops like the implicit empty "else" branch of an "if" expression. + [] + member inline _.Zero() : TaskCode<'TOverall, unit> = ResumableCode.Zero() + + member inline _.Return (value: 'T) : TaskCode<'T, 'T> = + TaskCode<'T, _>(fun sm -> + sm.Data.Result <- value + true) + + /// Chains together a step with its following step. + /// Note that this requires that the first step has no result. + /// This prevents constructs like `task { return 1; return 2; }`. + member inline _.Combine(task1: TaskCode<'TOverall, unit>, task2: TaskCode<'TOverall, 'T>) : TaskCode<'TOverall, 'T> = + ResumableCode.Combine(task1, task2) + + /// Builds a step that executes the body while the condition predicate is true. + member inline _.While ([] condition : unit -> bool, body : TaskCode<'TOverall, unit>) : TaskCode<'TOverall, unit> = + ResumableCode.While(condition, body) + + /// Wraps a step in a try/with. This catches exceptions both in the evaluation of the function + /// to retrieve the step, and in the continuation of the step (if any). + member inline _.TryWith (body: TaskCode<'TOverall, 'T>, catch: exn -> TaskCode<'TOverall, 'T>) : TaskCode<'TOverall, 'T> = + ResumableCode.TryWith(body, catch) + + /// Wraps a step in a try/finally. This catches exceptions both in the evaluation of the function + /// to retrieve the step, and in the continuation of the step (if any). + member inline _.TryFinally (body: TaskCode<'TOverall, 'T>, [] compensation : unit -> unit) : TaskCode<'TOverall, 'T> = + ResumableCode.TryFinally(body, ResumableCode<_,_>(fun _sm -> compensation(); true)) + + member inline _.For (sequence : seq<'T>, body : 'T -> TaskCode<'TOverall, unit>) : TaskCode<'TOverall, unit> = + ResumableCode.For(sequence, body) + + #if NETSTANDARD2_1 + member inline internal this.TryFinallyAsync(body: TaskCode<'TOverall, 'T>, compensation : unit -> ValueTask) : TaskCode<'TOverall, 'T> = + ResumableCode.TryFinallyAsync(body, ResumableCode<_,_>(fun sm -> + if __useResumableCode then + let mutable __stack_condition_fin = true + let __stack_vtask = compensation() + if not __stack_vtask.IsCompleted then + let mutable awaiter = __stack_vtask.GetAwaiter() + let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm) + __stack_condition_fin <- __stack_yield_fin + + if not __stack_condition_fin then + sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm) + + __stack_condition_fin + else + let vtask = compensation() + let mutable awaiter = vtask.GetAwaiter() + + let cont = + TaskResumptionFunc<'TOverall>( fun sm -> + awaiter.GetResult() |> ignore + true) + + // shortcut to continue immediately + if awaiter.IsCompleted then + true + else + sm.ResumptionDynamicInfo.ResumptionData <- (awaiter :> ICriticalNotifyCompletion) + sm.ResumptionDynamicInfo.ResumptionFunc <- cont + false + )) + + member inline this.Using<'Resource, 'TOverall, 'T when 'Resource :> IAsyncDisposable> (resource: 'Resource, body: 'Resource -> TaskCode<'TOverall, 'T>) : TaskCode<'TOverall, 'T> = + this.TryFinallyAsync( + (fun sm -> (body resource).Invoke(&sm)), + (fun () -> + if not (isNull (box resource)) then + resource.DisposeAsync() + else + ValueTask())) + #endif + + + type TaskBuilder() = + + inherit TaskBuilderBase() + + // This is the dynamic implementation - this is not used + // for statically compiled tasks. An executor (resumptionFuncExecutor) is + // registered with the state machine, plus the initial resumption. + // The executor stays constant throughout the execution, it wraps each step + // of the execution in a try/with. The resumption is changed at each step + // to represent the continuation of the computation. + static member RunDynamic(code: TaskCode<'T, 'T>) : Task<'T> = + let mutable sm = TaskStateMachine<'T>() + let initialResumptionFunc = TaskResumptionFunc<'T>(fun sm -> code.Invoke(&sm)) + let resumptionInfo = + { new TaskResumptionDynamicInfo<'T>(initialResumptionFunc) with + member info.MoveNext(sm) = + let mutable savedExn = null + try + sm.ResumptionDynamicInfo.ResumptionData <- null + let step = info.ResumptionFunc.Invoke(&sm) + if step then + sm.Data.MethodBuilder.SetResult(sm.Data.Result) + else + let mutable awaiter = sm.ResumptionDynamicInfo.ResumptionData :?> ICriticalNotifyCompletion + assert not (isNull awaiter) + sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm) + + with exn -> + savedExn <- exn + // Run SetException outside the stack unwind, see https://github.com/dotnet/roslyn/issues/26567 + match savedExn with + | null -> () + | exn -> sm.Data.MethodBuilder.SetException exn + + member _.SetStateMachine(sm, state) = + sm.Data.MethodBuilder.SetStateMachine(state) + } + sm.ResumptionDynamicInfo <- resumptionInfo + sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create() + sm.Data.MethodBuilder.Start(&sm) + sm.Data.MethodBuilder.Task + + static member inline Run(code : TaskCode<'T, 'T>) : Task<'T> = + if __useResumableCode then + __stateMachine, Task<'T>> + (MoveNextMethodImpl<_>(fun sm -> + //-- RESUMABLE CODE START + __resumeAt sm.ResumptionPoint + let mutable __stack_exn : Exception = null + try + let __stack_code_fin = code.Invoke(&sm) + if __stack_code_fin then + sm.Data.MethodBuilder.SetResult(sm.Data.Result) + with exn -> + __stack_exn <- exn + // Run SetException outside the stack unwind, see https://github.com/dotnet/roslyn/issues/26567 + match __stack_exn with + | null -> () + | exn -> sm.Data.MethodBuilder.SetException exn + //-- RESUMABLE CODE END + )) + (SetStateMachineMethodImpl<_>(fun sm state -> sm.Data.MethodBuilder.SetStateMachine(state))) + (AfterCode<_,_>(fun sm -> + sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create() + sm.Data.MethodBuilder.Start(&sm) + sm.Data.MethodBuilder.Task)) + else + TaskBuilder.RunDynamic(code) + + member inline _.Run(code : TaskCode<'T, 'T>) : Task<'T> = + TaskBuilder.Run(code) + + type BackgroundTaskBuilder() = + + inherit TaskBuilderBase() + + static member RunDynamic(code: TaskCode<'T, 'T>) : Task<'T> = + // backgroundTask { .. } escapes to a background thread where necessary + // See spec of ConfigureAwait(false) at https://devblogs.microsoft.com/dotnet/configureawait-faq/ + if isNull SynchronizationContext.Current && obj.ReferenceEquals(TaskScheduler.Current, TaskScheduler.Default) then + TaskBuilder.RunDynamic(code) + else + Task.Run<'T>(fun () -> TaskBuilder.RunDynamic(code)) + + //// Same as TaskBuilder.Run except the start is inside Task.Run if necessary + member inline _.Run(code : TaskCode<'T, 'T>) : Task<'T> = + if __useResumableCode then + __stateMachine, Task<'T>> + (MoveNextMethodImpl<_>(fun sm -> + //-- RESUMABLE CODE START + __resumeAt sm.ResumptionPoint + try + let __stack_code_fin = code.Invoke(&sm) + if __stack_code_fin then + sm.Data.MethodBuilder.SetResult(sm.Data.Result) + with exn -> + sm.Data.MethodBuilder.SetException exn + //-- RESUMABLE CODE END + )) + (SetStateMachineMethodImpl<_>(fun sm state -> sm.Data.MethodBuilder.SetStateMachine(state))) + (AfterCode<_,Task<'T>>(fun sm -> + // backgroundTask { .. } escapes to a background thread where necessary + // See spec of ConfigureAwait(false) at https://devblogs.microsoft.com/dotnet/configureawait-faq/ + if isNull SynchronizationContext.Current && obj.ReferenceEquals(TaskScheduler.Current, TaskScheduler.Default) then + sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create() + sm.Data.MethodBuilder.Start(&sm) + sm.Data.MethodBuilder.Task + else + let sm = sm // copy contents of state machine so we can capture it + Task.Run<'T>(fun () -> + let mutable sm = sm // host local mutable copy of contents of state machine on this thread pool thread + sm.Data.MethodBuilder <- AsyncTaskMethodBuilder<'T>.Create() + sm.Data.MethodBuilder.Start(&sm) + sm.Data.MethodBuilder.Task))) + else + BackgroundTaskBuilder.RunDynamic(code) + + module TaskBuilder = + + let task = TaskBuilder() + let backgroundTask = BackgroundTaskBuilder() + +namespace Microsoft.FSharp.Control.TaskBuilderExtensions + + open Microsoft.FSharp.Control + open System + open System.Runtime.CompilerServices + open System.Threading.Tasks + open Microsoft.FSharp.Core + open Microsoft.FSharp.Core.CompilerServices + open Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers + open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + + module LowPriority = + // Low priority extensions + type TaskBuilderBase with + + static member inline BindDynamic< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter , 'TOverall + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> 'TResult1)> + (sm: byref<_>, task: ^TaskLike, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : bool = + + let mutable awaiter = (^TaskLike: (member GetAwaiter : unit -> ^Awaiter)(task)) + + let cont = + (TaskResumptionFunc<'TOverall>( fun sm -> + let result = (^Awaiter : (member GetResult : unit -> 'TResult1)(awaiter)) + (continuation result).Invoke(&sm))) + + // shortcut to continue immediately + if (^Awaiter : (member get_IsCompleted : unit -> bool)(awaiter)) then + cont.Invoke(&sm) + else + sm.ResumptionDynamicInfo.ResumptionData <- (awaiter :> ICriticalNotifyCompletion) + sm.ResumptionDynamicInfo.ResumptionFunc <- cont + false + + member inline _.Bind< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter , 'TOverall + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> 'TResult1)> + (task: ^TaskLike, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> = + + TaskCode<'TOverall, _>(fun sm -> + if __useResumableCode then + //-- RESUMABLE CODE START + // Get an awaiter from the awaitable + let mutable awaiter = (^TaskLike: (member GetAwaiter : unit -> ^Awaiter)(task)) + + let mutable __stack_fin = true + if not (^Awaiter : (member get_IsCompleted : unit -> bool)(awaiter)) then + // This will yield with __stack_yield_fin = false + // This will resume with __stack_yield_fin = true + let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm) + __stack_fin <- __stack_yield_fin + + if __stack_fin then + let result = (^Awaiter : (member GetResult : unit -> 'TResult1)(awaiter)) + (continuation result).Invoke(&sm) + else + sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm) + false + else + TaskBuilderBase.BindDynamic< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter , 'TOverall>(&sm, task, continuation) + //-- RESUMABLE CODE END + ) + + member inline this.ReturnFrom< ^TaskLike, ^Awaiter, 'T + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> 'T)> + (task: ^TaskLike) : TaskCode< 'T, 'T> = + + this.Bind(task, (fun v -> this.Return v)) + + member inline _.Using<'Resource, 'TOverall, 'T when 'Resource :> IDisposable> (resource: 'Resource, body: 'Resource -> TaskCode<'TOverall, 'T>) = + ResumableCode.Using(resource, body) + + module HighPriority = + // High priority extensions + type TaskBuilderBase with + static member BindDynamic (sm: byref<_>, task: Task<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : bool = + let mutable awaiter = task.GetAwaiter() + + let cont = + (TaskResumptionFunc<'TOverall>(fun sm -> + let result = awaiter.GetResult() + (continuation result).Invoke(&sm))) + + // shortcut to continue immediately + if awaiter.IsCompleted then + cont.Invoke(&sm) + else + sm.ResumptionDynamicInfo.ResumptionData <- (awaiter :> ICriticalNotifyCompletion) + sm.ResumptionDynamicInfo.ResumptionFunc <- cont + false + + member inline _.Bind (task: Task<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> = + + TaskCode<'TOverall, _>(fun sm -> + if __useResumableCode then + //-- RESUMABLE CODE START + // Get an awaiter from the task + let mutable awaiter = task.GetAwaiter() + + let mutable __stack_fin = true + if not awaiter.IsCompleted then + // This will yield with __stack_yield_fin = false + // This will resume with __stack_yield_fin = true + let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm) + __stack_fin <- __stack_yield_fin + if __stack_fin then + let result = awaiter.GetResult() + (continuation result).Invoke(&sm) + else + sm.Data.MethodBuilder.AwaitUnsafeOnCompleted(&awaiter, &sm) + false + else + TaskBuilderBase.BindDynamic(&sm, task, continuation) + //-- RESUMABLE CODE END + ) + + member inline this.ReturnFrom (task: Task<'T>) : TaskCode<'T, 'T> = + this.Bind(task, (fun v -> this.Return v)) + + module MediumPriority = + open HighPriority + + // Medium priority extensions + type TaskBuilderBase with + member inline this.Bind (computation: Async<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> = + this.Bind (Async.StartAsTask computation, continuation) + + member inline this.ReturnFrom (computation: Async<'T>) : TaskCode<'T, 'T> = + this.ReturnFrom (Async.StartAsTask computation) + +#endif diff --git a/src/fsharp/FSharp.Core/tasks.fsi b/src/fsharp/FSharp.Core/tasks.fsi new file mode 100644 index 00000000000..e5ad31910ce --- /dev/null +++ b/src/fsharp/FSharp.Core/tasks.fsi @@ -0,0 +1,311 @@ +// TaskBuilder.fs - TPL task computation expressions for F# +// +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Microsoft.FSharp.Control + + #if !BUILDING_WITH_LKG && !BUILD_FROM_SOURCE + open System + open System.Runtime.CompilerServices + open System.Threading.Tasks + open Microsoft.FSharp.Core + open Microsoft.FSharp.Core.CompilerServices + open Microsoft.FSharp.Collections + + [] + [] + [] + /// + /// The extra data stored in ResumableStateMachine for tasks + /// + type TaskStateMachineData<'T> = + + /// + /// Holds the final result of the state machine + /// + [] + val mutable Result : 'T + + /// + /// Holds the MethodBuilder for the state machine + /// + [] + val mutable MethodBuilder : AsyncTaskMethodBuilder<'T> + + /// + /// This is used by the compiler as a template for creating state machine structs + /// + and [] + [] + TaskStateMachine<'TOverall> = ResumableStateMachine> + + /// + /// Represents the runtime continuation of a task state machine created dynamically + /// + and [] + [] + TaskResumptionFunc<'TOverall> = ResumptionFunc> + + /// + /// A special compiler-recognised delegate type for specifying blocks of task code + /// with access to the state machine. + /// + and [] + [] + TaskCode<'TOverall, 'T> = ResumableCode, 'T> + + /// + /// Contains methods to build tasks using the F# computation expression syntax + /// + [] + [] + type TaskBuilderBase = + + /// + /// Specifies the sequential composition of two units of task code. + /// + [] + member inline Combine: task1: TaskCode<'TOverall, unit> * task2: TaskCode<'TOverall, 'T> -> TaskCode<'TOverall, 'T> + + /// + /// Specifies the delayed execution of a unit of task code. + /// + [] + member inline Delay: f: (unit -> TaskCode<'TOverall, 'T>) -> TaskCode<'TOverall, 'T> + + /// + /// Specifies the iterative execution of a unit of task code. + /// + [] + member inline For: sequence: seq<'T> * body: ('T -> TaskCode<'TOverall, unit>) -> TaskCode<'TOverall, unit> + + /// + /// Specifies a unit of task code which returns a value + /// + [] + member inline Return: value: 'T -> TaskCode<'T, 'T> + + /// + /// Specifies a unit of task code which excuted using try/finally semantics + /// + [] + member inline TryFinally: body: TaskCode<'TOverall, 'T> * [] compensation: (unit -> unit) -> TaskCode<'TOverall, 'T> + + /// + /// Specifies a unit of task code which excuted using try/with semantics + /// + [] + member inline TryWith: body: TaskCode<'TOverall, 'T> * catch: (exn -> TaskCode<'TOverall, 'T>) -> TaskCode<'TOverall, 'T> + + #if NETSTANDARD2_1 + /// + /// Specifies a unit of task code which binds to the resource implementing IAsyncDisposable and disposes it asynchronously + /// + [] + member inline Using<'Resource, 'TOverall, 'T when 'Resource :> IAsyncDisposable> : resource: 'Resource * body: ('Resource -> TaskCode<'TOverall, 'T>) -> TaskCode<'TOverall, 'T> + #endif + + /// + /// Specifies the iterative execution of a unit of task code. + /// + [] + member inline While: condition: (unit -> bool) * body: TaskCode<'TOverall, unit> -> TaskCode<'TOverall, unit> + + /// + /// Specifies a unit of task code which produces no result + /// + [] + [] + member inline Zero: unit -> TaskCode<'TOverall, unit> + + /// + /// Contains methods to build tasks using the F# computation expression syntax + /// + [] + [] + type TaskBuilder = + inherit TaskBuilderBase + + /// + /// The entry point for the dynamic implementation of the corresponding operation. Do not use directly, only used when executing quotations that involve tasks or other reflective execution of F# code. + /// + [] + static member RunDynamic: code: TaskCode<'T, 'T> -> Task<'T> + + /// Hosts the task code in a state machine and starts the task. + [] + member inline Run: code: TaskCode<'T, 'T> -> Task<'T> + + /// + /// Contains methods to build tasks using the F# computation expression syntax + /// + [] + [] + type BackgroundTaskBuilder = + inherit TaskBuilderBase + + /// + /// The entry point for the dynamic implementation of the corresponding operation. Do not use directly, only used when executing quotations that involve tasks or other reflective execution of F# code. + /// + [] + static member RunDynamic: code: TaskCode<'T, 'T> -> Task<'T> + + /// + /// Hosts the task code in a state machine and starts the task, executing in the threadpool using Task.Run + /// + [] + member inline Run: code: TaskCode<'T, 'T> -> Task<'T> + + /// Contains the `task` computation expression builder. + [] + [] + module TaskBuilder = + + /// + /// Builds a task using computation expression syntax. + /// + [] + val task: TaskBuilder + + /// + /// Builds a task using computation expression syntax which switches to execute on a background thread if not + /// already doing so. + /// + /// + /// If the task is created on a foreground thread (where is non-null) + /// its body is executed on a background thread using . + /// If created on a background thread (where is null) it is executed immeidately + /// immediately on that thread. + /// + [] + val backgroundTask: BackgroundTaskBuilder + + +/// Contains the `task` computation expression builder. +namespace Microsoft.FSharp.Control.TaskBuilderExtensions + + open System + open System.Runtime.CompilerServices + open System.Threading.Tasks + open Microsoft.FSharp.Core + open Microsoft.FSharp.Control + + /// + /// Contains low-priority overloads for the `task` computation expression builder. + /// + // + // Note: they are low priority because they are auto-opened first, and F# has a rule + // that extension method opened later in sequence get higher priority + // + // AutoOpen is by assembly attribute to get sequencing of AutoOpen correct and + // so each gives different priority + [] + module LowPriority = + + type TaskBuilderBase with + /// + /// Specifies a unit of task code which draws a result from a task-like value + /// satisfying the GetAwaiter pattern and calls a continuation. + /// + [] + member inline Bind< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall > : + task: ^TaskLike * + continuation: ( 'TResult1 -> TaskCode<'TOverall, 'TResult2>) + -> TaskCode<'TOverall, 'TResult2> + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> 'TResult1) + + /// + /// Specifies a unit of task code which draws its result from a task-like value + /// satisfying the GetAwaiter pattern. + /// + [] + member inline ReturnFrom< ^TaskLike, ^Awaiter, 'T> : + task: ^TaskLike + -> TaskCode< 'T, 'T > + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> 'T) + + /// + /// The entry point for the dynamic implementation of the corresponding operation. Do not use directly, only used when executing quotations that involve tasks or other reflective execution of F# code. + /// + [] + static member inline BindDynamic< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall > : + sm: byref> * + task: ^TaskLike * + continuation: ( 'TResult1 -> TaskCode<'TOverall, 'TResult2>) + -> bool + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> 'TResult1) + + /// + /// Specifies a unit of task code which binds to the resource implementing IDisposable and disposes it synchronously + /// + [] + member inline Using: resource: 'Resource * body: ('Resource -> TaskCode<'TOverall, 'T>) -> TaskCode<'TOverall, 'T> when 'Resource :> IDisposable + + /// + /// Contains medium-priority overloads for the `task` computation expression builder. + /// + [] + module MediumPriority = + + type TaskBuilderBase with + + /// + /// Specifies a unit of task code which draws a result from an F# async value then calls a continuation. + /// + [] + member inline Bind: + computation: Async<'TResult1> * + continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>) + -> TaskCode<'TOverall, 'TResult2> + + /// + /// Specifies a unit of task code which draws a result from an F# async value. + /// + [] + member inline ReturnFrom: + computation: Async<'T> + -> TaskCode<'T, 'T> + + /// + /// Contains high-priority overloads for the `task` computation expression builder. + /// + [] + module HighPriority = + + type TaskBuilderBase with + /// + /// Specifies a unit of task code which draws a result from a task then calls a continuation. + /// + [] + member inline Bind: + task: Task<'TResult1> * + continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>) + -> TaskCode<'TOverall, 'TResult2> + + /// + /// Specifies a unit of task code which draws a result from a task. + /// + [] + member inline ReturnFrom: + task: Task<'T> + -> TaskCode<'T, 'T> + + /// + /// The entry point for the dynamic implementation of the corresponding operation. Do not use directly, only used when executing quotations that involve tasks or other reflective execution of F# code. + /// + [] + static member BindDynamic: + sm: byref> * + task: Task<'TResult1> * + continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>) + -> bool +#endif diff --git a/src/fsharp/FindUnsolved.fs b/src/fsharp/FindUnsolved.fs index 3728ec59aa8..a4d284e879a 100644 --- a/src/fsharp/FindUnsolved.fs +++ b/src/fsharp/FindUnsolved.fs @@ -170,7 +170,7 @@ and accExprs cenv env exprs = and accTargets cenv env m ty targets = Array.iter (accTarget cenv env m ty) targets -and accTarget cenv env _m _ty (TTarget(_vs, e, _)) = +and accTarget cenv env _m _ty (TTarget(_vs, e, _, _)) = accExpr cenv env e and accDTree cenv env x = diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 0d4d17043fa..5ee0558e976 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -23,9 +23,12 @@ open FSharp.Compiler.AbstractIL.ILX.Types open FSharp.Compiler.AttributeChecking open FSharp.Compiler.CompilerGlobalState open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.Features +open FSharp.Compiler.Infos open FSharp.Compiler.Import open FSharp.Compiler.Infos open FSharp.Compiler.LowerCallsAndSeqs +open FSharp.Compiler.LowerStateMachines open FSharp.Compiler.Syntax open FSharp.Compiler.Syntax.PrettyNaming open FSharp.Compiler.SyntaxTreeOps @@ -389,7 +392,13 @@ let ComputeTypeAccess (tref: ILTypeRef) hidden = /// Indicates how type parameters are mapped to IL type variables [] -type TypeReprEnv(reprs: Map, count: int) = +type TypeReprEnv(reprs: Map, count: int, templateReplacement: (TyconRef * ILType * TyparInst) option) = + + static let empty = TypeReprEnv(count = 0, reprs = Map.empty, templateReplacement = None) + /// Get the template replacement information used when using struct types for state machines based on a "template" struct + member __.TemplateReplacement = templateReplacement + + member __.WithTemplateReplacement(tcref, ilty, tpinst) = TypeReprEnv(reprs, count, Some (tcref, ilty, tpinst)) /// Lookup a type parameter member _.Item (tp: Typar, m: range) = @@ -403,7 +412,7 @@ type TypeReprEnv(reprs: Map, count: int) = /// then it is ignored, since it doesn't correspond to a .NET type parameter. member tyenv.AddOne (tp: Typar) = if IsNonErasedTypar tp then - TypeReprEnv(reprs.Add (tp.Stamp, uint16 count), count + 1) + TypeReprEnv(reprs.Add (tp.Stamp, uint16 count), count + 1, templateReplacement) else tyenv @@ -415,20 +424,23 @@ type TypeReprEnv(reprs: Map, count: int) = member _.Count = count /// Get the empty environment, where no type parameters are in scope. - static member Empty = - TypeReprEnv(count = 0, reprs = Map.empty) + static member Empty = empty + + /// Reset to the empty environment, where no type parameters are in scope. + member eenv.ResetTypars() = + TypeReprEnv(count = 0, reprs = Map.empty, templateReplacement = eenv.TemplateReplacement) /// Get the environment for a fixed set of type parameters - static member ForTypars tps = - TypeReprEnv.Empty.Add tps + member eenv.ForTypars tps = + eenv.ResetTypars().Add tps /// Get the environment for within a type definition - static member ForTycon (tycon: Tycon) = - TypeReprEnv.ForTypars (tycon.TyparsNoRange) + member eenv.ForTycon (tycon: Tycon) = + eenv.ForTypars (tycon.TyparsNoRange) /// Get the environment for generating a reference to items within a type definition - static member ForTyconRef (tycon: TyconRef) = - TypeReprEnv.ForTycon tycon.Deref + member eenv.ForTyconRef (tycon: TyconRef) = + eenv.ForTycon tycon.Deref //-------------------------------------------------------------------------- // Generate type references @@ -496,10 +508,12 @@ and GenILTyAppAux amap m tyenv (tref, boxity, ilTypeOpt) tinst = | Some ilType -> ilType // monomorphic types include a cached ilType to avoid reallocation of an ILType node -and GenNamedTyAppAux (amap: ImportMap) m tyenv ptrsOK tcref tinst = +and GenNamedTyAppAux (amap: ImportMap) m (tyenv: TypeReprEnv) ptrsOK tcref tinst = let g = amap.g + match tyenv.TemplateReplacement with + | Some (tcref2, ilty, _) when tyconRefEq g tcref tcref2 -> ilty + | _ -> let tinst = DropErasedTyargs tinst - // See above note on ptrsOK if ptrsOK = PtrTypesOK && tyconRefEq g tcref g.nativeptr_tcr && (freeInTypes CollectTypars tinst).FreeTypars.IsEmpty then GenNamedTyAppAux amap m tyenv ptrsOK g.ilsigptr_tcr tinst @@ -567,7 +581,7 @@ and GenUnionRef (amap: ImportMap) m (tcref: TyconRef) = | ValueNone -> failwith "GenUnionRef m" | ValueSome funion -> cached funion.CompiledRepresentation (fun () -> - let tyenvinner = TypeReprEnv.ForTycon tycon + let tyenvinner = TypeReprEnv.Empty.ForTycon tycon match tcref.CompiledRepresentation with | CompiledTypeRepr.ILAsmOpen _ -> failwith "GenUnionRef m: unexpected ASM tyrep" | CompiledTypeRepr.ILAsmNamed (tref, _, _) -> @@ -665,9 +679,18 @@ let GenFieldSpecForStaticField (isInteractive, g, ilContainerTy, vspec: Val, nm, let ilFieldContainerTy = mkILTyForCompLoc (CompLocForInitClass cloc) mkILFieldSpecInTy (ilFieldContainerTy, fieldName, ilTy) -let GenRecdFieldRef m cenv tyenv (rfref: RecdFieldRef) tyargs = - let tyenvinner = TypeReprEnv.ForTycon rfref.Tycon - mkILFieldSpecInTy(GenTyApp cenv.amap m tyenv rfref.TyconRef.CompiledRepresentation tyargs, + +let GenRecdFieldRef m cenv (tyenv: TypeReprEnv) (rfref: RecdFieldRef) tyargs = + // Fixup references to the fields of a struct machine template + match tyenv.TemplateReplacement with + | Some (tcref2, ilty, inst) when tyconRefEq cenv.g rfref.TyconRef tcref2 -> + mkILFieldSpecInTy(ilty, + ComputeFieldName rfref.Tycon rfref.RecdField, + GenType cenv.amap m tyenv (instType inst rfref.RecdField.FormalType)) + | _ -> + let tyenvinner = TypeReprEnv.Empty.ForTycon rfref.Tycon + let ilty = GenTyApp cenv.amap m tyenv rfref.TyconRef.CompiledRepresentation tyargs + mkILFieldSpecInTy(ilty, ComputeFieldName rfref.Tycon rfref.RecdField, GenType cenv.amap m tyenvinner rfref.RecdField.FormalType) @@ -788,9 +811,6 @@ type IlxClosureInfo = /// The ILX specification for the closure cloSpec: IlxClosureSpec - /// The attributes that get attached to the closure class - cloAttribs: Attribs - /// The generic parameters for the closure, i.e. the type variables it captures cloILGenericParams: IL.ILGenericParameterDefs @@ -895,13 +915,16 @@ and Mark = and sequel = | EndFilter - /// Exit a 'handler' block - /// The integer says which local to save result in - | LeaveHandler of (bool (* finally? *) * int * Mark) + /// Exit a 'handler' block. The integer says which local to save result in + | LeaveHandler of + isFinally: bool * + whereToSaveOpt: (int * ILType) option * + afterHandler: Mark * + hasResult: bool /// Branch to the given mark | Br of Mark - + /// Execute the given comparison-then-branch instructions on the result of the expression /// If the branch isn't taken then drop through. | CmpThenBrOrContinue of Pops * ILInstr list @@ -939,6 +962,10 @@ and IlxGenEnv = /// Indicates the default "place" for stuff we're currently generating cloc: CompileLocation + /// The sequel to use for an "early exit" in a state machine, e.g. a return from the middle of an + /// async block + exitSequel: sequel + /// Hiding information down the signature chain, used to compute what's public to the assembly sigToImplRemapInfo: (Remap * SignatureHidingInfo) list @@ -981,9 +1008,9 @@ let SetIsInLoop isInLoop eenv = if eenv.isInLoop = isInLoop then eenv else { eenv with isInLoop = isInLoop } -let ReplaceTyenv tyenv (eenv: IlxGenEnv) = {eenv with tyenv = tyenv } +let EnvForTypars tps eenv = {eenv with tyenv = eenv.tyenv.ForTypars tps } -let EnvForTypars tps eenv = {eenv with tyenv = TypeReprEnv.ForTypars tps } +let EnvForTycon tps eenv = {eenv with tyenv = eenv.tyenv.ForTycon tps } let AddTyparsToEnv typars (eenv: IlxGenEnv) = {eenv with tyenv = eenv.tyenv.Add typars} @@ -1032,6 +1059,9 @@ let AddStorageForVal (g: TcGlobals) (v, s) eenv = let AddStorageForLocalVals g vals eenv = List.foldBack (fun (v, s) acc -> AddStorageForVal g (v, notlazy s) acc) vals eenv +let AddTemplateReplacement eenv (tcref, ilty, inst) = + { eenv with tyenv = eenv.tyenv.WithTemplateReplacement (tcref, ilty, inst) } + let AddStorageForLocalWitness eenv (w,s) = { eenv with witnessesInScope = eenv.witnessesInScope.SetItem (w, s) } @@ -1072,7 +1102,7 @@ let GetMethodSpecForMemberVal amap g (memberInfo: ValMemberInfo) (vref: ValRef) let tps, witnessInfos, curriedArgInfos, returnTy, retInfo = assert(vref.ValReprInfo.IsSome) GetTopValTypeInCompiledForm g vref.ValReprInfo.Value numEnclosingTypars vref.Type m - let tyenvUnderTypars = TypeReprEnv.ForTypars tps + let tyenvUnderTypars = TypeReprEnv.Empty.ForTypars tps let flatArgInfos = List.concat curriedArgInfos let isCtor = (memberInfo.MemberFlags.MemberKind = SynMemberKind.Constructor) let cctor = (memberInfo.MemberFlags.MemberKind = SynMemberKind.ClassConstructor) @@ -1189,7 +1219,7 @@ let ComputeStorageForFSharpFunctionOrFSharpExtensionMember amap (g: TcGlobals) c let nm = vref.CompiledName g.CompilerGlobalState let numEnclosingTypars = CountEnclosingTyparsOfActualParentOfVal vref.Deref let (tps, witnessInfos, curriedArgInfos, returnTy, retInfo) = GetTopValTypeInCompiledForm g topValInfo numEnclosingTypars vref.Type m - let tyenvUnderTypars = TypeReprEnv.ForTypars tps + let tyenvUnderTypars = TypeReprEnv.Empty.ForTypars tps let (methodArgTys, paramInfos) = curriedArgInfos |> List.concat |> List.unzip let ilMethodArgTys = GenParamTypes amap m tyenvUnderTypars false methodArgTys let ilRetTy = GenReturnType amap m tyenvUnderTypars returnTy @@ -1235,7 +1265,7 @@ let ComputeStorageForTopVal (amap, g, optIntraAssemblyInfo: IlxGenIntraAssemblyI if vref.Deref.IsCompiledAsStaticPropertyWithoutField then let nm = "get_"+nm - let tyenvUnderTypars = TypeReprEnv.ForTypars [] + let tyenvUnderTypars = TypeReprEnv.Empty.ForTypars [] let ilRetTy = GenType amap m tyenvUnderTypars vref.Type let ty = mkILTyForCompLoc cloc let mspec = mkILStaticMethSpecInTy (ty, nm, [], ilRetTy, []) @@ -1656,7 +1686,7 @@ type AssemblyBuilder(cenv: cenv, anonTypeTable: AnonTypeGenerationTable) as mgbu let ilTypeDefAttribs = mkILCustomAttrs [ g.CompilerGeneratedAttribute; mkCompilationMappingAttr g (int SourceConstructFlags.RecordType) ] - let ilInterfaceTys = [ for (ity, _, _) in tcaug.tcaug_interfaces -> GenType cenv.amap m (TypeReprEnv.ForTypars tps) ity ] + let ilInterfaceTys = [ for (ity, _, _) in tcaug.tcaug_interfaces -> GenType cenv.amap m (TypeReprEnv.Empty.ForTypars tps) ity ] let ilTypeDef = mkILGenericClass (ilTypeRef.Name, ILTypeDefAccess.Public, ilGenericParams, ilBaseTy, ilInterfaceTys, @@ -2136,7 +2166,8 @@ let LocalScope nm cgbuf (f: (Mark * Mark) -> 'a) : 'a = CG.SetMarkToHere cgbuf endScope res -let compileSequenceExpressions = true // try (System.Environment.GetEnvironmentVariable("COMPILED_SEQ") <> null) with _ -> false +let compileSequenceExpressions = true // try (System.Environment.GetEnvironmentVariable("FSHARP_COMPILED_SEQ") <> null) with _ -> false +let compileStateMachineExpressions = true // try (System.Environment.GetEnvironmentVariable("FSHARP_COMPILED_STATEMACHINES") <> null) with _ -> false //------------------------------------------------------------------------- // Sequence Point Logic @@ -2206,11 +2237,18 @@ let rec FirstEmittedCodeWillBeDebugPoint g sp expr = | Expr.LetRec (binds, body, _, _) -> binds |> List.exists (BindingEmitsDebugPoint g) || (binds |> List.forall (BindingEmitsNoCode g) && FirstEmittedCodeWillBeDebugPoint g sp body) - | Expr.Sequential (_, _, NormalSeq, spSeq, _) -> + | Expr.Sequential (stmt1, expr2, NormalSeq, spSeq, _) -> + match spSeq with + | DebugPointAtSequential.SuppressNeither -> FirstEmittedCodeWillBeDebugPoint g sp stmt1 + | DebugPointAtSequential.SuppressExpr -> FirstEmittedCodeWillBeDebugPoint g sp stmt1 + | DebugPointAtSequential.SuppressStmt -> FirstEmittedCodeWillBeDebugPoint g sp expr2 + | DebugPointAtSequential.SuppressBoth -> false + | Expr.Sequential (expr1, stmt2, ThenDoSeq, spSeq, _) -> match spSeq with - | DebugPointAtSequential.Both -> true - | DebugPointAtSequential.StmtOnly -> true - | DebugPointAtSequential.ExprOnly -> false + | DebugPointAtSequential.SuppressNeither -> FirstEmittedCodeWillBeDebugPoint g sp expr1 + | DebugPointAtSequential.SuppressExpr -> FirstEmittedCodeWillBeDebugPoint g sp stmt2 + | DebugPointAtSequential.SuppressStmt -> FirstEmittedCodeWillBeDebugPoint g sp expr1 + | DebugPointAtSequential.SuppressBoth -> false | Expr.Match (DebugPointAtBinding.Yes _, _, _, _, _, _) -> true | Expr.Op ((TOp.TryWith (DebugPointAtTry.Yes _, _) | TOp.TryFinally (DebugPointAtTry.Yes _, _) @@ -2370,7 +2408,29 @@ and GenExprPreSteps (cenv: cenv) (cgbuf: CodeGenBuffer) eenv sp expr sequel = GenSequenceExpr cenv cgbuf eenv info sequel true | None -> - false + + match LowerStateMachineExpr cenv.g expr with + | LoweredStateMachineResult.Lowered res -> + checkLanguageFeatureError cenv.g.langVersion LanguageFeature.ResumableStateMachines expr.Range + GenStructStateMachine cenv cgbuf eenv res sequel + true + | LoweredStateMachineResult.UseAlternative (msg, altExpr) -> + checkLanguageFeatureError cenv.g.langVersion LanguageFeature.ResumableStateMachines expr.Range + warning(Error(FSComp.SR.reprStateMachineNotCompilable(msg), expr.Range)) + GenExpr cenv cgbuf eenv sp altExpr sequel + true + | LoweredStateMachineResult.NoAlternative msg -> + checkLanguageFeatureError cenv.g.langVersion LanguageFeature.ResumableStateMachines expr.Range + errorR(Error(FSComp.SR.reprStateMachineNotCompilableNoAlternative(msg), expr.Range)) + GenDefaultValue cenv cgbuf eenv (tyOfExpr cenv.g expr, expr.Range) + true + | LoweredStateMachineResult.NotAStateMachine -> + match expr with + | IfUseResumableStateMachinesExpr g (_thenExpr, elseExpr) -> + GenExpr cenv cgbuf eenv sp elseExpr sequel + true + | _ -> + false and GenExprAux (cenv: cenv) (cgbuf: CodeGenBuffer) eenv sp expr sequel = let g = cenv.g @@ -2497,7 +2557,7 @@ and GenExprAux (cenv: cenv) (cgbuf: CodeGenBuffer) eenv sp expr sequel = CG.EmitInstr cgbuf (pop 0) Push0 (I_br label) // NOTE: discard sequel | TOp.Return, [e], _ -> - GenExpr cenv cgbuf eenv SPSuppress e Return + GenExpr cenv cgbuf eenv SPSuppress e eenv.exitSequel // NOTE: discard sequel | TOp.Return, [], _ -> GenSequel cenv eenv.cloc cgbuf ReturnVoid @@ -2531,6 +2591,7 @@ and GenExprs cenv cgbuf eenv es = List.iter (fun e -> GenExpr cenv cgbuf eenv SPSuppress e Continue) es and CodeGenMethodForExpr cenv mgbuf (spReq, entryPointInfo, methodName, eenv, alreadyUsedArgs, expr0, sequel0) = + let eenv = { eenv with exitSequel = sequel0 } let _, code = CodeGenMethod cenv mgbuf (entryPointInfo, methodName, eenv, alreadyUsedArgs, (fun cgbuf eenv -> GenExpr cenv cgbuf eenv spReq expr0 sequel0), @@ -2541,9 +2602,17 @@ and CodeGenMethodForExpr cenv mgbuf (spReq, entryPointInfo, methodName, eenv, al // Generate sequels //-------------------------------------------------------------------------- -(* does the sequel discard its result, and if so what does it do next? *) +/// Adjust the sequel for an implicit discard (e.g. a discard that occurs by +/// not generating a 'unit' expression at all) and sequelAfterDiscard sequel = match sequel with + | LeaveHandler (isFinally, whereToSaveResultOpt, afterHandler, true) -> + // If we're not saving the result as we leave a handler and we're doing a discard + // then we can just adjust the sequel to record the fact we've implicitly done a discard + if isFinally || whereToSaveResultOpt.IsNone then + Some (LeaveHandler (isFinally, whereToSaveResultOpt, afterHandler, false)) + else + None | DiscardThen sequel -> Some sequel | EndLocalScope(sq, mark) -> sequelAfterDiscard sq |> Option.map (fun sq -> EndLocalScope(sq, mark)) | _ -> None @@ -2599,12 +2668,17 @@ and GenSequel cenv cloc cgbuf sequel = cgbuf.EmitStartOfHiddenCode() CG.EmitInstr cgbuf (pop 0) Push0 AI_nop CG.EmitInstr cgbuf (pop 0) Push0 (I_br x.CodeLabel) - | LeaveHandler (isFinally, whereToSaveResult, x) -> - if isFinally then - CG.EmitInstr cgbuf (pop 1) Push0 AI_pop - else - EmitSetLocal cgbuf whereToSaveResult - CG.EmitInstr cgbuf (pop 0) Push0 (if isFinally then I_endfinally else I_leave(x.CodeLabel)) + | LeaveHandler (isFinally, whereToSaveResultOpt, afterHandler, hasResult) -> + if hasResult then + if isFinally then + CG.EmitInstr cgbuf (pop 1) Push0 AI_pop + else + match whereToSaveResultOpt with + | None -> + CG.EmitInstr cgbuf (pop 1) Push0 AI_pop + | Some (whereToSaveResult, _) -> + EmitSetLocal cgbuf whereToSaveResult + CG.EmitInstr cgbuf (pop 0) Push0 (if isFinally then I_endfinally else I_leave(afterHandler.CodeLabel)) | EndFilter -> CG.EmitInstr cgbuf (pop 1) Push0 I_endfilter ) @@ -2747,19 +2821,27 @@ and GenLinearExpr cenv cgbuf eenv sp expr sequel preSteps (contf: FakeUnit -> Fa // Compiler generated sequential executions result in suppressions of sequence points on both // left and right of the sequence - let spAction, spExpr = + let spStmt, spExpr = (match spSeq with - | DebugPointAtSequential.Both -> SPAlways, SPAlways - | DebugPointAtSequential.StmtOnly -> SPSuppress, sp - | DebugPointAtSequential.ExprOnly -> sp, SPSuppress) + | DebugPointAtSequential.SuppressNeither -> SPAlways, SPAlways + | DebugPointAtSequential.SuppressStmt -> SPSuppress, sp + | DebugPointAtSequential.SuppressExpr -> sp, SPSuppress + | DebugPointAtSequential.SuppressBoth -> SPSuppress, SPSuppress) match specialSeqFlag with | NormalSeq -> - GenExpr cenv cgbuf eenv spAction e1 discard + GenExpr cenv cgbuf eenv spStmt e1 discard GenLinearExpr cenv cgbuf eenv spExpr e2 sequel true contf | ThenDoSeq -> - GenExpr cenv cgbuf eenv spExpr e1 Continue - GenExpr cenv cgbuf eenv spAction e2 discard - GenSequel cenv eenv.cloc cgbuf sequel + let g = cenv.g + let isUnit = isUnitTy g (tyOfExpr g e1) + if isUnit then + GenExpr cenv cgbuf eenv spExpr e1 discard + GenExpr cenv cgbuf eenv spStmt e2 discard + GenUnitThenSequel cenv eenv e2.Range eenv.cloc cgbuf sequel + else + GenExpr cenv cgbuf eenv spExpr e1 Continue + GenExpr cenv cgbuf eenv spStmt e2 discard + GenSequel cenv eenv.cloc cgbuf sequel contf Fake | Expr.Let (bind, body, _, _) -> @@ -2771,7 +2853,7 @@ and GenLinearExpr cenv cgbuf eenv sp expr sequel preSteps (contf: FakeUnit -> Fa let startScope, endScope as scopeMarks = StartDelayedLocalScope "let" cgbuf let eenv = AllocStorageForBind cenv cgbuf scopeMarks eenv bind let spBind = GenDebugPointForBind cenv cgbuf bind - GenBindingAfterDebugPoint cenv cgbuf eenv spBind bind (Some startScope) + GenBindingAfterDebugPoint cenv cgbuf eenv spBind bind false (Some startScope) // Work out if we need a sequence point for the body. For any "user" binding then the body gets SPAlways. // For invisible compiler-generated bindings we just use "sp", unless its body is another invisible binding @@ -2883,7 +2965,7 @@ and GenAllocRecd cenv cgbuf eenv ctorInfo (tcref,argtys,args,m) sequel = | RecdExpr -> GenExprs cenv cgbuf eenv args // generate a reference to the record constructor - let tyenvinner = TypeReprEnv.ForTyconRef tcref + let tyenvinner = eenv.tyenv.ForTyconRef tcref CG.EmitInstr cgbuf (pop args.Length) (Push [ty]) (mkNormalNewobj (mkILCtorMethSpecForTy (ty, relevantFields |> List.map (fun f -> GenType cenv.amap m tyenvinner f.FormalType) ))) @@ -3197,7 +3279,7 @@ and GenUntupledArgExpr cenv cgbuf eenv m argInfos expr = let bind = mkCompGenBind locv expr LocalScope "untuple" cgbuf (fun scopeMarks -> let eenvinner = AllocStorageForBind cenv cgbuf scopeMarks eenv bind - GenBinding cenv cgbuf eenvinner bind + GenBinding cenv cgbuf eenvinner bind false let tys = destRefTupleTy g ty assert (tys.Length = numRequiredExprs) argInfos |> List.iteri (fun i _ -> GenGetTupleField cenv cgbuf eenvinner (tupInfoRef, loce, tys, i, m) Continue) @@ -3348,6 +3430,15 @@ and GenApp (cenv: cenv) cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel = CG.EmitInstr cgbuf (pop 2) (Push [g.ilg.typ_Bool]) AI_ceq GenSequel cenv eenv.cloc cgbuf sequel + | Expr.Val (v, _, m), _, _ + when valRefEq g v g.cgh__resumeAt_vref || + valRefEq g v g.cgh__resumableEntry_vref || + valRefEq g v g.cgh__stateMachine_vref + -> + errorR(Error(FSComp.SR.ilxgenInvalidConstructInStateMachineDuringCodegen(v.DisplayName), m)) + CG.EmitInstr cgbuf (pop 0) (Push [g.ilg.typ_Object]) AI_ldnull + GenSequel cenv eenv.cloc cgbuf sequel + // Emit "methodhandleof" calls as ldtoken instructions // // The token for the "GenericMethodDefinition" is loaded @@ -3703,7 +3794,8 @@ and GenIndirectCall cenv cgbuf eenv (functy, tyargs, curriedArgs, m) sequel = // Generate try expressions //-------------------------------------------------------------------------- -and GenTry cenv cgbuf eenv scopeMarks (e1, m, resty, spTry) = +and GenTry cenv cgbuf eenv scopeMarks (e1, m, resultTy, spTry) = + let g = cenv.g let sp = match spTry with | DebugPointAtTry.Yes m -> CG.EmitSeqPoint cgbuf m; SPAlways @@ -3714,22 +3806,33 @@ and GenTry cenv cgbuf eenv scopeMarks (e1, m, resty, spTry) = let startTryMark = CG.GenerateMark cgbuf "startTryMark" let endTryMark = CG.GenerateDelayMark cgbuf "endTryMark" let afterHandler = CG.GenerateDelayMark cgbuf "afterHandler" - let eenvinner = {eenvinner with withinSEH = true} - let ilResultTy = GenType cenv.amap m eenvinner.tyenv resty + let ilResultTyOpt = + if isUnitTy g resultTy then + None + else + Some (GenType cenv.amap m eenvinner.tyenv resultTy) + + let whereToSaveOpt, eenvinner = + match ilResultTyOpt with + | None -> None, eenvinner + | Some ilResultTy -> + // Ensure that we have an g.CompilerGlobalState + assert(cenv.g.CompilerGlobalState |> Option.isSome) + let whereToSave, _realloc, eenvinner = + AllocLocal cenv cgbuf eenvinner true (cenv.g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName ("tryres", m), ilResultTy, false) (startTryMark, endTryMark) + Some (whereToSave, ilResultTy), eenvinner - let whereToSave, _realloc, eenvinner = - // Ensure that we have an g.CompilerGlobalState - assert(cenv.g.CompilerGlobalState |> Option.isSome) - AllocLocal cenv cgbuf eenvinner true (cenv.g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName ("tryres", m), ilResultTy, false) (startTryMark, endTryMark) + let exitSequel = LeaveHandler (false, whereToSaveOpt, afterHandler, true) + let eenvinner = {eenvinner with withinSEH = true; exitSequel = exitSequel} // Generate the body of the try. In the normal case (DebugPointAtTry.Yes) we generate a sequence point // both on the 'try' keyword and on the start of the expression in the 'try'. For inlined code and // compiler generated 'try' blocks (i.e. DebugPointAtTry.No, used for the try/finally implicit // in a 'use' or 'foreach'), we suppress the sequence point - GenExpr cenv cgbuf eenvinner sp e1 (LeaveHandler (false, whereToSave, afterHandler)) + GenExpr cenv cgbuf eenvinner sp e1 exitSequel CG.SetMarkToHere cgbuf endTryMark let tryMarks = (startTryMark.CodeLabel, endTryMark.CodeLabel) - whereToSave, eenvinner, stack, tryMarks, afterHandler, ilResultTy + whereToSaveOpt, eenvinner, stack, tryMarks, afterHandler and GenTryWith cenv cgbuf eenv (e1, vf: Val, ef, vh: Val, eh, m, resty, spTry, spWith) sequel = let g = cenv.g @@ -3737,7 +3840,7 @@ and GenTryWith cenv cgbuf eenv (e1, vf: Val, ef, vh: Val, eh, m, resty, spTry, s // Save the stack - gross because IL flushes the stack at the exn. handler // note: eenvinner notes spill vars are live LocalScope "trystack" cgbuf (fun scopeMarks -> - let whereToSave, eenvinner, stack, tryMarks, afterHandler, ilResultTy = GenTry cenv cgbuf eenv scopeMarks (e1, m, resty, spTry) + let whereToSaveOpt, eenvinner, stack, tryMarks, afterHandler = GenTry cenv cgbuf eenv scopeMarks (e1, m, resty, spTry) // Now the filter and catch blocks @@ -3746,6 +3849,7 @@ and GenTryWith cenv cgbuf eenv (e1, vf: Val, ef, vh: Val, eh, m, resty, spTry, s let startOfFilter = CG.GenerateMark cgbuf "startOfFilter" let afterFilter = CG.GenerateDelayMark cgbuf "afterFilter" let (sequelOnBranches, afterJoin, stackAfterJoin, sequelAfterJoin) = GenJoinPoint cenv cgbuf "filter" eenv g.int_ty m EndFilter + let eenvinner = { eenvinner with exitSequel = sequelOnBranches } // We emit the sequence point for the 'with' keyword span on the start of the filter // block. However the targets of the filter block pattern matching should not get any // sequence points (they will be 'true'/'false' values indicating if the exception has been @@ -3783,7 +3887,8 @@ and GenTryWith cenv cgbuf eenv (e1, vf: Val, ef, vh: Val, eh, m, resty, spTry, s CG.EmitInstr cgbuf (pop 1) (Push [g.iltyp_Exception]) (I_castclass g.iltyp_Exception) GenStoreVal cenv cgbuf eenvinner vh.Range vh - GenExpr cenv cgbuf eenvinner SPAlways eh (LeaveHandler (false, whereToSave, afterHandler)) + let exitSequel = LeaveHandler (false, whereToSaveOpt, afterHandler, true) + GenExpr cenv cgbuf eenvinner SPAlways eh exitSequel let endOfHandler = CG.GenerateMark cgbuf "endOfHandler" let handlerMarks = (startOfHandler.CodeLabel, endOfHandler.CodeLabel) @@ -3801,8 +3906,10 @@ and GenTryWith cenv cgbuf eenv (e1, vf: Val, ef, vh: Val, eh, m, resty, spTry, s GenStoreVal cenv cgbuf eenvinner m vh - GenExpr cenv cgbuf eenvinner SPAlways eh (LeaveHandler (false, whereToSave, afterHandler)) - + let exitSequel = LeaveHandler (false, whereToSaveOpt, afterHandler, true) + let eenvinner = { eenvinner with exitSequel = exitSequel } + GenExpr cenv cgbuf eenvinner SPAlways eh exitSequel + let endOfHandler = CG.GenerateMark cgbuf "endOfHandler" let handlerMarks = (startOfHandler.CodeLabel, endOfHandler.CodeLabel) ILExceptionClause.TypeCatch(g.ilg.typ_Object, handlerMarks) @@ -3819,8 +3926,12 @@ and GenTryWith cenv cgbuf eenv (e1, vf: Val, ef, vh: Val, eh, m, resty, spTry, s (* Restore the stack and load the result *) EmitRestoreStack cgbuf stack (* RESTORE *) - EmitGetLocal cgbuf ilResultTy whereToSave - GenSequel cenv eenv.cloc cgbuf sequel + match whereToSaveOpt with + | Some (whereToSave, ilResultTy) -> + EmitGetLocal cgbuf ilResultTy whereToSave + GenSequel cenv eenv.cloc cgbuf sequel + | None -> + GenUnitThenSequel cenv eenv m eenv.cloc cgbuf sequel ) @@ -3829,7 +3940,7 @@ and GenTryFinally cenv cgbuf eenv (bodyExpr, handlerExpr, m, resty, spTry, spFin // note: eenvinner notes spill vars are live LocalScope "trystack" cgbuf (fun scopeMarks -> - let whereToSave, eenvinner, stack, tryMarks, afterHandler, ilResultTy = GenTry cenv cgbuf eenv scopeMarks (bodyExpr, m, resty, spTry) + let whereToSaveOpt, eenvinner, stack, tryMarks, afterHandler = GenTry cenv cgbuf eenv scopeMarks (bodyExpr, m, resty, spTry) // Now the catch/finally block let startOfHandler = CG.GenerateMark cgbuf "startOfHandler" @@ -3841,7 +3952,8 @@ and GenTryFinally cenv cgbuf eenv (bodyExpr, handlerExpr, m, resty, spTry, spFin | DebugPointAtFinally.Body -> SPAlways | DebugPointAtFinally.No -> SPSuppress - GenExpr cenv cgbuf eenvinner sp handlerExpr (LeaveHandler (true, whereToSave, afterHandler)) + let exitSequel = LeaveHandler (true, whereToSaveOpt, afterHandler, true) + GenExpr cenv cgbuf eenvinner sp handlerExpr exitSequel let endOfHandler = CG.GenerateMark cgbuf "endOfHandler" let handlerMarks = (startOfHandler.CodeLabel, endOfHandler.CodeLabel) cgbuf.EmitExceptionClause @@ -3854,8 +3966,12 @@ and GenTryFinally cenv cgbuf eenv (bodyExpr, handlerExpr, m, resty, spTry, spFin // Restore the stack and load the result cgbuf.EmitStartOfHiddenCode() EmitRestoreStack cgbuf stack - EmitGetLocal cgbuf ilResultTy whereToSave - GenSequel cenv eenv.cloc cgbuf sequel + match whereToSaveOpt with + | Some (whereToSave, ilResultTy) -> + EmitGetLocal cgbuf ilResultTy whereToSave + GenSequel cenv eenv.cloc cgbuf sequel + | None -> + GenUnitThenSequel cenv eenv m eenv.cloc cgbuf sequel ) //-------------------------------------------------------------------------- @@ -3955,7 +4071,7 @@ and GenForLoop cenv cgbuf eenv (spFor, v, e1, dir, e2, loopBody, m) sequel = // Generate while-loop //-------------------------------------------------------------------------- -and GenWhileLoop cenv cgbuf eenv (spWhile, e1, e2, m) sequel = +and GenWhileLoop cenv cgbuf eenv (spWhile, condExpr, bodyExpr, m) sequel = let eenv = SetIsInLoop true eenv let finish = CG.GenerateDelayMark cgbuf "while_finish" let startTest = CG.GenerateMark cgbuf "startTest" @@ -3966,9 +4082,9 @@ and GenWhileLoop cenv cgbuf eenv (spWhile, e1, e2, m) sequel = | DebugPointAtWhile.No -> SPSuppress // SEQUENCE POINTS: Emit a sequence point to cover all of 'while e do' - GenExpr cenv cgbuf eenv spCondition e1 (CmpThenBrOrContinue (pop 1, [ I_brcmp(BI_brfalse, finish.CodeLabel) ])) + GenExpr cenv cgbuf eenv spCondition condExpr (CmpThenBrOrContinue (pop 1, [ I_brcmp(BI_brfalse, finish.CodeLabel) ])) - GenExpr cenv cgbuf eenv SPAlways e2 (DiscardThen (Br startTest)) + GenExpr cenv cgbuf eenv SPAlways bodyExpr (DiscardThen (Br startTest)) CG.SetMarkToHere cgbuf finish // SEQUENCE POINTS: Emit a sequence point to cover 'done' if present @@ -4442,17 +4558,26 @@ and GenFormalSlotsig m cenv eenv (TSlotSig(_, ty, ctps, mtps, paraml, returnTy)) let ilTy = GenType cenv.amap m eenv.tyenv ty let eenvForSlotSig = EnvForTypars (ctps @ mtps) eenv let ilParams = paraml |> List.map (GenSlotParam m cenv eenvForSlotSig) - let ilRetTy = GenReturnType cenv.amap m eenvForSlotSig.tyenv returnTy - let ilRet = mkILReturn ilRetTy - let ilRet = - match returnTy with - | None -> ilRet - | Some ty -> - match GenReadOnlyAttributeIfNecessary cenv.g ty with - | Some attr -> ilRet.WithCustomAttrs (mkILCustomAttrs (ilRet.CustomAttrs.AsList @ [attr])) - | None -> ilRet + let ilRet = GenFormalReturnType m cenv eenvForSlotSig returnTy ilTy, ilParams, ilRet +and GenOverridesSpec cenv eenv slotsig m = + let (TSlotSig(nameOfOverridenMethod, _, _, methodTypars, _, _)) = slotsig + let ilOverrideTy, ilOverrideParams, ilOverrideRet = GenFormalSlotsig m cenv eenv slotsig + let ilOverrideTyRef = ilOverrideTy.TypeRef + let ilOverrideMethRef = mkILMethRef(ilOverrideTyRef, ILCallingConv.Instance, nameOfOverridenMethod, List.length (DropErasedTypars methodTypars), typesOfILParams ilOverrideParams, ilOverrideRet.Type) + OverridesSpec(ilOverrideMethRef, ilOverrideTy) + +and GenFormalReturnType m cenv eenvFormal returnTy : ILReturn = + let ilRetTy = GenReturnType cenv.amap m eenvFormal.tyenv returnTy + let ilRet = mkILReturn ilRetTy + match returnTy with + | None -> ilRet + | Some ty -> + match GenReadOnlyAttributeIfNecessary cenv.g ty with + | Some attr -> ilRet.WithCustomAttrs (mkILCustomAttrs (ilRet.CustomAttrs.AsList @ [attr])) + | None -> ilRet + and instSlotParam inst (TSlotParam(nm, ty, inFlag, fl2, fl3, attrs)) = TSlotParam(nm, instType inst ty, inFlag, fl2, fl3, attrs) @@ -4478,20 +4603,18 @@ and GenNameOfOverridingMethod cenv (useMethodImpl, slotsig) = else nameOfOverridenMethod -and GenMethodImpl cenv eenv (useMethodImpl, (TSlotSig(nameOfOverridenMethod, _, _, _, _, _) as slotsig)) m = - let ilOverrideTy, ilOverrideParams, ilOverrideRet = GenFormalSlotsig m cenv eenv slotsig +and GenMethodImpl cenv eenv (useMethodImpl, slotsig) m = + let ilOverridesSpec = GenOverridesSpec cenv eenv slotsig m let nameOfOverridingMethod = GenNameOfOverridingMethod cenv (useMethodImpl, slotsig) nameOfOverridingMethod, (fun (ilTyForOverriding, methTyparsOfOverridingMethod) -> - let ilOverrideTyRef = ilOverrideTy.TypeRef - let ilOverrideMethRef = mkILMethRef(ilOverrideTyRef, ILCallingConv.Instance, nameOfOverridenMethod, List.length (DropErasedTypars methTyparsOfOverridingMethod), typesOfILParams ilOverrideParams, ilOverrideRet.Type) let eenvForOverrideBy = AddTyparsToEnv methTyparsOfOverridingMethod eenv let ilParamsOfOverridingMethod, ilReturnOfOverridingMethod = GenActualSlotsig m cenv eenvForOverrideBy slotsig methTyparsOfOverridingMethod [] let ilOverrideMethGenericParams = GenGenericParams cenv eenvForOverrideBy methTyparsOfOverridingMethod let ilOverrideMethGenericArgs = mkILFormalGenericArgs 0 ilOverrideMethGenericParams let ilOverrideBy = mkILInstanceMethSpecInTy(ilTyForOverriding, nameOfOverridingMethod, typesOfILParams ilParamsOfOverridingMethod, ilReturnOfOverridingMethod.Type, ilOverrideMethGenericArgs) - { Overrides = OverridesSpec(ilOverrideMethRef, ilOverrideTy) + { Overrides = ilOverridesSpec OverrideBy = ilOverrideBy }) and bindBaseOrThisVarOpt cenv eenv baseValOpt = @@ -4546,19 +4669,220 @@ and GenObjectMethod cenv eenvinner (cgbuf: CodeGenBuffer) useMethodImpl tmethod let mdef = mdef.With(customAttrs = mkILCustomAttrs ilAttribs) [(useMethodImpl, methodImplGenerator, methTyparsOfOverridingMethod), mdef] -and GenObjectExpr cenv cgbuf eenvouter expr (baseType, baseValOpt, basecall, overrides, interfaceImpls, m) sequel = +and GenStructStateMachine cenv cgbuf eenvouter (res: LoweredStateMachine) sequel = + + let (LoweredStateMachine + (templateStructTy, dataTy, stateVars, thisVars, + (moveNextThisVar, moveNextBody), + (setStateMachineThisVar, setStateMachineStateVar, setStateMachineBody), + (afterCodeThisVar, afterCodeBody))) = res + let m = moveNextBody.Range let g = cenv.g - let cloinfo, _, eenvinner = GetIlxClosureInfo cenv m false false [] eenvouter expr + let amap = cenv.amap + + let stateVarsSet = stateVars |> List.map (fun vref -> vref.Deref) |> Zset.ofList valOrder + + // Find the free variables of the closure, to make them further fields of the object. + let cloinfo, _, eenvinner = + // State vars are only populated for state machine objects + // + // Like in GenSequenceExpression we pretend any stateVars and the stateMachineVar are bound in the outer environment. This prevents the being + // considered true free variables that need to be passed to the constructor. + // + // Note, the 'let' bindings for the stateVars have already been transformed to 'set' expressions, and thus the stateVars are now + // free variables of the expression. + let eenvouter = eenvouter |> AddStorageForLocalVals g (stateVars |> List.map (fun v -> v.Deref, Local(0, false, None))) + let eenvouter = eenvouter |> AddStorageForLocalVals g (thisVars |> List.map (fun v -> v.Deref, Local(0, false, None))) + let eenvouter = eenvouter |> AddStorageForLocalVals g [ (moveNextThisVar, Local(0, false, None)) ] + GetIlxClosureInfo cenv m ILBoxity.AsValue false false (mkLocalValRef moveNextThisVar :: thisVars) eenvouter moveNextBody + + let cloFreeVars = cloinfo.cloFreeVars + + let ilCloFreeVars = cloinfo.ilCloAllFreeVars + let ilCloGenericFormals = cloinfo.cloILGenericParams + let ilCloGenericActuals = cloinfo.cloSpec.GenericArgs + let ilCloTypeRef = cloinfo.cloSpec.TypeRef + let ilCloTy = mkILValueTy ilCloTypeRef ilCloGenericActuals + + // The closure implements what ever interfaces the template implements. + let interfaceTys = GetImmediateInterfacesOfType SkipUnrefInterfaces.Yes g cenv.amap m templateStructTy + + let ilInterfaceTys = List.map (GenType cenv.amap m eenvinner.tyenv) interfaceTys + + let super = g.iltyp_ValueType + + let templateTyconRef, templateTypeArgs = destAppTy g templateStructTy + let templateTypeInst = mkTyconRefInst templateTyconRef templateTypeArgs + let eenvinner = AddTemplateReplacement eenvinner (templateTyconRef, ilCloTy, templateTypeInst) + + let infoReader = InfoReader.InfoReader(g, cenv.amap) + + // We codegen the IResumableStateMachine implementation for each generated struct type + let getResumptionPointThisVar, getResumptionPointBody = + let fieldName = "ResumptionPoint" + let thisVar = moveNextThisVar // reusing the this var from the MoveNext implementation + let finfo = + match infoReader.GetRecordOrClassFieldsOfType(Some fieldName, AccessibilityLogic.AccessorDomain.AccessibleFromSomewhere, m, templateStructTy) with + | [finfo] -> finfo + | _ -> error(InternalError(sprintf "expected class field %s not found" fieldName, m)) + thisVar, mkRecdFieldGetViaExprAddr (exprForVal m thisVar, finfo.RecdFieldRef, finfo.TypeInst, m) + + let (getDataThisVar, getDataBody), (setDataThisVar, setDataValueVar, setDataBody) = + let fieldName = "Data" + let thisVar = moveNextThisVar // reusing the this var from the MoveNext implementation + let setDataValueVar, setDataValueExpr = mkCompGenLocal m "value" dataTy + let finfo = + match infoReader.GetRecordOrClassFieldsOfType(Some fieldName, AccessibilityLogic.AccessorDomain.AccessibleFromSomewhere, m, templateStructTy) with + | [finfo] -> finfo + | _ -> error(InternalError(sprintf "expected class field %s not found" fieldName, m)) + (thisVar, mkRecdFieldGetViaExprAddr (exprForVal m thisVar, finfo.RecdFieldRef, finfo.TypeInst, m)), + (thisVar, setDataValueVar, mkRecdFieldSetViaExprAddr (exprForVal m thisVar, finfo.RecdFieldRef, finfo.TypeInst, setDataValueExpr, m)) + + let methods = + [ ((mkLocalValRef moveNextThisVar::thisVars), [], g.mk_IAsyncStateMachine_ty, "MoveNext", moveNextBody); + ([mkLocalValRef setStateMachineThisVar], [setStateMachineStateVar], g.mk_IAsyncStateMachine_ty, "SetStateMachine", setStateMachineBody); + ([mkLocalValRef getResumptionPointThisVar], [], g.mk_IResumableStateMachine_ty dataTy, "get_ResumptionPoint", getResumptionPointBody); + ([mkLocalValRef getDataThisVar], [], g.mk_IResumableStateMachine_ty dataTy, "get_Data", getDataBody); + ([mkLocalValRef setDataThisVar], [setDataValueVar], g.mk_IResumableStateMachine_ty dataTy, "set_Data", setDataBody); ] + + let mdefs = + [ for (thisVals, argVals, interfaceTy, imethName, bodyR) in methods do + let eenvinner = eenvinner |> AddStorageForLocalVals g [(moveNextThisVar, Arg 0) ] + let m = bodyR.Range + let implementedMeth = + match InfoReader.TryFindIntrinsicMethInfo infoReader m AccessibilityLogic.AccessorDomain.AccessibleFromSomewhere imethName interfaceTy with + | [meth] when meth.IsInstance -> meth + | _ -> error(InternalError(sprintf "expected method %s not found" imethName, m)) + let argTys = implementedMeth.GetParamTypes(cenv.amap, m, []) |> List.concat + let retTy = implementedMeth.GetCompiledReturnTy(cenv.amap, m, []) + let ilRetTy = GenReturnType cenv.amap m eenvinner.tyenv retTy + let ilArgTys = argTys |> GenTypes cenv.amap m eenvinner.tyenv + if ilArgTys.Length <> argVals.Length then + error(InternalError(sprintf "expected method arg count of %d, got %d for method %s" argVals.Length ilArgTys.Length imethName, m)) + let eenvinner = eenvinner |> AddStorageForLocalVals g (thisVals |> List.map (fun v -> (v.Deref, Arg 0))) + let eenvinner = eenvinner |> AddStorageForLocalVals g (argVals |> List.mapi (fun i v -> v, Arg (i+1))) + let sequel = if retTy.IsNone then discardAndReturnVoid else Return + let ilCode = CodeGenMethodForExpr cenv cgbuf.mgbuf (SPSuppress, [], imethName, eenvinner, 1+argVals.Length, bodyR, sequel) + let ilParams = (ilArgTys,argVals) ||> List.map2 (fun ty v -> mkILParamNamed(v.LogicalName, ty)) + mkILNonGenericVirtualMethod(imethName, ILMemberAccess.Public, ilParams, mkILReturn ilRetTy, MethodBody.IL (notlazy ilCode)) ] + + let mimpls = + [ for ((_thisVals, _argVals, interfaceTy, imethName, bodyR), mdef) in (List.zip methods mdefs) do + let m = bodyR.Range + let implementedMeth = + match InfoReader.TryFindIntrinsicMethInfo infoReader m AccessibilityLogic.AccessorDomain.AccessibleFromSomewhere imethName interfaceTy with + | [meth] when meth.IsInstance -> meth + | _ -> error(InternalError(sprintf "expected method %s not found" imethName, m)) + + let slotsig = implementedMeth.GetSlotSig(amap, m) + let ilOverridesSpec = GenOverridesSpec cenv eenvinner slotsig m + let ilOverrideBy = mkILInstanceMethSpecInTy(ilCloTy, imethName, mdef.ParameterTypes, mdef.Return.Type, []) + { Overrides = ilOverridesSpec + OverrideBy = ilOverrideBy } ] + + let fdefs = + [ // Fields copied from the template struct + for templateFld in infoReader.GetRecordOrClassFieldsOfType (None, AccessibilityLogic.AccessorDomain.AccessibleFromSomewhere, m, templateStructTy) do + // Suppress the "ResumptionDynamicInfo" from generated state machines + if templateFld.Name <> "ResumptionDynamicInfo" then + let access = ComputeMemberAccess false + let fty = GenType cenv.amap m eenvinner.tyenv templateFld.FieldType + let fdef = + ILFieldDef(name = templateFld.Name, fieldType = fty, attributes = enum 0, data = None, literalValue = None, offset = None, marshal = None, customAttrs = mkILCustomAttrs []) + .WithAccess(access) + .WithStatic(false) + yield fdef + + // Fields for captured variables + for ilCloFreeVar in ilCloFreeVars do + let access = ComputeMemberAccess false + let fdef = + ILFieldDef(name = ilCloFreeVar.fvName, fieldType = ilCloFreeVar.fvType, attributes = enum 0, + data = None, literalValue = None, offset = None, marshal = None, customAttrs = mkILCustomAttrs []) + .WithAccess(access) + .WithStatic(false) + yield fdef ] + + let cloTypeDef = + ILTypeDef(name = ilCloTypeRef.Name, + layout = ILTypeDefLayout.Auto, + attributes = enum 0, + genericParams = ilCloGenericFormals, + customAttrs = mkILCustomAttrs([ g.CompilerGeneratedAttribute; mkCompilationMappingAttr g (int SourceConstructFlags.Closure) ]), + fields = mkILFields fdefs, + events= emptyILEvents, + properties = emptyILProperties, + methods= mkILMethods mdefs, + methodImpls = mkILMethodImpls mimpls, + nestedTypes = emptyILTypeDefs, + implements = ilInterfaceTys, + extends = Some super, + securityDecls = emptyILSecurityDecls) + .WithSealed(true) + .WithSpecialName(true) + .WithAccess(ComputeTypeAccess ilCloTypeRef true) + .WithLayout(ILTypeDefLayout.Auto) + .WithEncoding(ILDefaultPInvokeEncoding.Auto) + .WithInitSemantics(ILTypeInit.BeforeField) + + cgbuf.mgbuf.AddTypeDef(ilCloTypeRef, cloTypeDef, false, false, None) + + CountClosure() + LocalScope "machine" cgbuf (fun scopeMarks -> + let ilMachineAddrTy = ILType.Byref ilCloTy + + // The local for the state machine + let locIdx, realloc, _ = AllocLocal cenv cgbuf eenvinner true (g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName ("machine", m), ilCloTy, false) scopeMarks + + // The local for the state machine address + let locIdx2, _realloc2, _ = AllocLocal cenv cgbuf eenvinner true (g.CompilerGlobalState.Value.IlxGenNiceNameGenerator.FreshCompilerGeneratedName (afterCodeThisVar.DisplayName, m), ilMachineAddrTy, false) scopeMarks + + // Zero-initialize the machine + EmitInitLocal cgbuf ilCloTy locIdx + + // Initialize the address-of-machine local + CG.EmitInstr cgbuf (pop 0) (Push [ ilMachineAddrTy ]) (I_ldloca (uint16 locIdx) ) + CG.EmitInstr cgbuf (pop 1) (Push [ ]) (I_stloc (uint16 locIdx2) ) + + let eenvinner = eenvinner |> AddStorageForLocalVals g [(afterCodeThisVar, Local (locIdx2, realloc, None)) ] + + // Initialize the closure variables + for (fv, ilv) in Seq.zip cloFreeVars cloinfo.ilCloAllFreeVars do + if stateVarsSet.Contains fv then + // zero-initialize the state var + if realloc then + CG.EmitInstr cgbuf (pop 0) (Push [ ilMachineAddrTy ]) (I_ldloc (uint16 locIdx2) ) + GenDefaultValue cenv cgbuf eenvouter (fv.Type, m) + CG.EmitInstr cgbuf (pop 2) (Push [ ]) (mkNormalStfld (mkILFieldSpecInTy (ilCloTy, ilv.fvName, ilv.fvType))) + else + // initialize the captured var + CG.EmitInstr cgbuf (pop 0) (Push [ ilMachineAddrTy ]) (I_ldloc (uint16 locIdx2) ) + GenGetLocalVal cenv cgbuf eenvouter m fv None + CG.EmitInstr cgbuf (pop 2) (Push [ ]) (mkNormalStfld (mkILFieldSpecInTy (ilCloTy, ilv.fvName, ilv.fvType))) + + // Generate the start expression - eenvinner is used as it contains the binding for machineAddrVar + GenExpr cenv cgbuf eenvinner SPSuppress afterCodeBody sequel + + ) + +and GenObjectExpr cenv cgbuf eenvouter objExpr (baseType, baseValOpt, basecall, overrides, interfaceImpls, m) sequel = + let g = cenv.g + + // Find the free variables of the closure, to make them further fields of the object. + // + // Note, the 'let' bindings for the stateVars have already been transformed to 'set' expressions, and thus the stateVars are now + // free variables of the expression. + let cloinfo, _, eenvinner = GetIlxClosureInfo cenv m ILBoxity.AsObject false false [] eenvouter objExpr - let cloAttribs = cloinfo.cloAttribs let ilCloLambdas = cloinfo.ilCloLambdas let cloName = cloinfo.cloName + let cloSpec = cloinfo.cloSpec let ilCloAllFreeVars = cloinfo.ilCloAllFreeVars let ilCloGenericFormals = cloinfo.cloILGenericParams let ilCloGenericActuals = cloinfo.cloSpec.GenericArgs let ilCloRetTy = cloinfo.ilCloFormalReturnTy - let ilCloTypeRef = cloinfo.cloSpec.TypeRef + let ilCloTypeRef = cloSpec.TypeRef let ilTyForOverriding = mkILBoxedTy ilCloTypeRef ilCloGenericActuals let eenvinner = bindBaseOrThisVarOpt cenv eenvinner baseValOpt @@ -4581,14 +4905,19 @@ and GenObjectExpr cenv cgbuf eenvouter expr (baseType, baseValOpt, basecall, ove let interfaceTys = interfaceImpls |> List.map (fst >> GenType cenv.amap m eenvinner.tyenv) - let attrs = GenAttrs cenv eenvinner cloAttribs let super = (if isInterfaceTy g baseType then g.ilg.typ_Object else ilCloRetTy) let interfaceTys = interfaceTys @ (if isInterfaceTy g baseType then [ilCloRetTy] else []) - let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, ilCloGenericFormals, attrs, ilCloAllFreeVars, ilCloLambdas, ilCtorBody, mdefs, mimpls, super, interfaceTys, Some cloinfo.cloSpec) + let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, ilCloGenericFormals, [], ilCloAllFreeVars, ilCloLambdas, ilCtorBody, mdefs, mimpls, super, interfaceTys, Some cloinfo.cloSpec) for cloTypeDef in cloTypeDefs do cgbuf.mgbuf.AddTypeDef(ilCloTypeRef, cloTypeDef, false, false, None) - GenClosureAlloc cenv cgbuf eenvouter (cloinfo, m) + + CountClosure() + GenWitnessArgsFromWitnessInfos cenv cgbuf eenvouter m cloinfo.cloWitnessInfos + for fv in cloinfo.cloFreeVars do + GenGetLocalVal cenv cgbuf eenvouter m fv None + + CG.EmitInstr cgbuf (pop ilCloAllFreeVars.Length) (Push [ EraseClosures.mkTyOfLambdas g.ilxPubCloEnv ilCloLambdas]) (I_newobj (cloSpec.Constructor, None)) GenSequel cenv eenvouter.cloc cgbuf sequel and GenSequenceExpr @@ -4606,8 +4935,8 @@ and GenSequenceExpr eenvouter |> AddStorageForLocalVals g (stateVars |> List.map (fun v -> v.Deref, Local(0, false, None))) // Get the free variables. Make a lambda to pretend that the 'nextEnumeratorValRef' is bound (it is an argument to GenerateNext) - let (cloAttribs, cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilCloTypeRef: ILTypeRef, ilCloAllFreeVars, eenvinner) = - GetIlxClosureFreeVars cenv m [] eenvouter [] (mkLambda m nextEnumeratorValRef.Deref (generateNextExpr, g.int32_ty)) + let (cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilCloTypeRef: ILTypeRef, ilCloAllFreeVars, eenvinner) = + GetIlxClosureFreeVars cenv m [] ILBoxity.AsObject eenvouter [] (mkLambda m nextEnumeratorValRef.Deref (generateNextExpr, g.int32_ty)) let ilCloSeqElemTy = GenType cenv.amap m eenvinner.tyenv seqElemTy let cloRetTy = mkSeqTy g seqElemTy @@ -4615,7 +4944,7 @@ and GenSequenceExpr let ilCloRetTyOuter = GenType cenv.amap m eenvouter.tyenv cloRetTy let ilCloEnumeratorTy = GenType cenv.amap m eenvinner.tyenv (mkIEnumeratorTy g seqElemTy) let ilCloEnumerableTy = GenType cenv.amap m eenvinner.tyenv (mkSeqTy g seqElemTy) - let ilCloBaseTy = GenType cenv.amap m eenvinner.tyenv (mkAppTy g.seq_base_tcr [seqElemTy]) + let ilCloBaseTy = GenType cenv.amap m eenvinner.tyenv (g.mk_GeneratedSequenceBase_ty seqElemTy) let ilCloGenericParams = GenGenericParams cenv eenvinner cloFreeTyvars // Create a new closure class with a single "MoveNext" method that implements the iterator. @@ -4673,9 +5002,8 @@ and GenSequenceExpr let ilCtorBody = mkILSimpleStorageCtor(None, Some ilCloBaseTy.TypeSpec, ilCloTyInner, [], [], ILMemberAccess.Assembly).MethodBody - let attrs = GenAttrs cenv eenvinner cloAttribs let cloMethods = [generateNextMethod; closeMethod; checkCloseMethod; lastGeneratedMethod; getFreshMethod] - let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, ilCloGenericParams, attrs, ilCloAllFreeVars, ilCloLambdas, ilCtorBody, cloMethods, [], ilCloBaseTy, [], Some ilxCloSpec) + let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, ilCloGenericParams, [], ilCloAllFreeVars, ilCloLambdas, ilCtorBody, cloMethods, [], ilCloBaseTy, [], Some ilxCloSpec) for cloTypeDef in cloTypeDefs do cgbuf.mgbuf.AddTypeDef(ilCloTypeRef, cloTypeDef, false, false, None) @@ -4759,7 +5087,7 @@ and GenGenericArgs m (tyenv: TypeReprEnv) tps = /// Generate a local type function contract class and implementation and GenClosureAsLocalTypeFunction cenv (cgbuf: CodeGenBuffer) eenv isLocalTypeFunc thisVars expr m = let g = cenv.g - let cloinfo, body, eenvinner = GetIlxClosureInfo cenv m isLocalTypeFunc true thisVars eenv expr + let cloinfo, body, eenvinner = GetIlxClosureInfo cenv m ILBoxity.AsObject isLocalTypeFunc true thisVars eenv expr let ilCloTypeRef = cloinfo.cloSpec.TypeRef let entryPointInfo = thisVars |> List.map (fun v -> (v, BranchCallClosure (cloinfo.cloArityInfo))) // Now generate the actual closure implementation w.r.t. eenvinner @@ -4786,7 +5114,7 @@ and GenClosureAsLocalTypeFunction cenv (cgbuf: CodeGenBuffer) eenv isLocalTypeFu and GenClosureAsFirstClassFunction cenv (cgbuf: CodeGenBuffer) eenv isLocalTypeFunc thisVars m expr = let g = cenv.g - let cloinfo, body, eenvinner = GetIlxClosureInfo cenv m isLocalTypeFunc true thisVars eenv expr + let cloinfo, body, eenvinner = GetIlxClosureInfo cenv m ILBoxity.AsObject isLocalTypeFunc true thisVars eenv expr let entryPointInfo = thisVars |> List.map (fun v -> (v, BranchCallClosure (cloinfo.cloArityInfo))) let ilCloTypeRef = cloinfo.cloSpec.TypeRef @@ -4849,7 +5177,7 @@ and GenFreevar cenv m eenvouter tyenvinner (fv: Val) = #endif | _ -> GenType cenv.amap m tyenvinner fv.Type -and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) eenvouter takenNames expr = +and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenvouter takenNames expr = let g = cenv.g // Choose a base name for the closure @@ -4904,13 +5232,11 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) eenvouter takenNames ex let cloFreeTyvars = cloFreeTyvars.FreeTypars |> Zset.elements - let cloAttribs = [] - let eenvinner = eenvouter |> EnvForTypars cloFreeTyvars let ilCloTyInner = let ilCloGenericParams = GenGenericParams cenv eenvinner cloFreeTyvars - mkILFormalBoxedTy ilCloTypeRef ilCloGenericParams + mkILFormalNamedTy boxity ilCloTypeRef ilCloGenericParams // If generating a named closure, add the closure itself as a var, available via "arg0" . // The latter doesn't apply for the delegate implementation of closures. @@ -4958,15 +5284,15 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) eenvouter takenNames ex let eenvinner = eenvinner |> AddStorageForLocalVals g ilCloFreeVarStorage // Return a various results - (cloAttribs, cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) + (cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) + -and GetIlxClosureInfo cenv m isLocalTypeFunc canUseStaticField thisVars eenvouter expr = +and GetIlxClosureInfo cenv m boxity isLocalTypeFunc canUseStaticField thisVars eenvouter expr = let g = cenv.g let returnTy = match expr with | Expr.Lambda (_, _, _, _, _, _, returnTy) | Expr.TyLambda (_, _, _, _, returnTy) -> returnTy - | Expr.Obj (_, ty, _, _, _, _, _) -> ty - | _ -> failwith "GetIlxClosureInfo: not a lambda expression" + | _ -> tyOfExpr g expr // Determine the structure of the closure. We do this before analyzing free variables to // determine the taken argument names. @@ -4987,8 +5313,8 @@ and GetIlxClosureInfo cenv m isLocalTypeFunc canUseStaticField thisVars eenvoute let takenNames = vs |> List.map (fun v -> v.CompiledName g.CompilerGlobalState) // Get the free variables and the information about the closure, add the free variables to the environment - let (cloAttribs, cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) = - GetIlxClosureFreeVars cenv m thisVars eenvouter takenNames expr + let (cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilCloTypeRef, ilCloAllFreeVars, eenvinner) = + GetIlxClosureFreeVars cenv m thisVars boxity eenvouter takenNames expr // Put the type and value arguments into the environment let rec getClosureArgs eenv numArgs tvsl (vs: Val list) = @@ -5037,8 +5363,7 @@ and GetIlxClosureInfo cenv m isLocalTypeFunc canUseStaticField thisVars eenvoute cloILGenericParams = ilCloGenericFormals cloFreeVars=cloFreeVars cloFreeTyvars=cloFreeTyvars - cloWitnessInfos = cloWitnessInfos - cloAttribs=cloAttribs } + cloWitnessInfos = cloWitnessInfos } cloinfo, body, eenvinner /// Generate a new delegate construction including a closure class if necessary. This is a lot like generating function closures @@ -5069,8 +5394,8 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod((TSlotSig(_, deleg // Work out the free type variables for the morphing thunk let takenNames = List.map nameOfVal tmvs - let (cloAttribs, cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilDelegeeTypeRef, ilCloAllFreeVars, eenvinner) = - GetIlxClosureFreeVars cenv m [] eenvouter takenNames expr + let (cloFreeTyvars, cloWitnessInfos, cloFreeVars, ilDelegeeTypeRef, ilCloAllFreeVars, eenvinner) = + GetIlxClosureFreeVars cenv m [] ILBoxity.AsObject eenvouter takenNames expr let ilDelegeeGenericParams = GenGenericParams cenv eenvinner cloFreeTyvars let ilDelegeeGenericActualsInner = mkILFormalGenericArgs 0 ilDelegeeGenericParams @@ -5104,10 +5429,9 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod((TSlotSig(_, deleg let ilCtorBody = delegeeCtorMeth.MethodBody let ilCloLambdas = Lambdas_return ilCtxtDelTy - let ilAttribs = GenAttrs cenv eenvinner cloAttribs let cloTypeDefs = (if useStaticClosure then GenStaticDelegateClosureTypeDefs else GenClosureTypeDefs) - cenv (ilDelegeeTypeRef, ilDelegeeGenericParams, ilAttribs, ilCloAllFreeVars, ilCloLambdas, ilCtorBody, [delegeeInvokeMeth], [], g.ilg.typ_Object, [], None) + cenv (ilDelegeeTypeRef, ilDelegeeGenericParams, [], ilCloAllFreeVars, ilCloLambdas, ilCtorBody, [delegeeInvokeMeth], [], g.ilg.typ_Object, [], None) for cloTypeDef in cloTypeDefs do cgbuf.mgbuf.AddTypeDef(ilDelegeeTypeRef, cloTypeDef, false, false, None) CountClosure() @@ -5241,7 +5565,7 @@ and GenDecisionTreeAndTargetsInner cenv cgbuf inplabOpt stackAtTargets eenv tree let startScope, endScope as scopeMarks = StartDelayedLocalScope "dtreeBind" cgbuf let eenv = AllocStorageForBind cenv cgbuf scopeMarks eenv bind let sp = GenDebugPointForBind cenv cgbuf bind - GenBindingAfterDebugPoint cenv cgbuf eenv sp bind (Some startScope) + GenBindingAfterDebugPoint cenv cgbuf eenv sp bind false (Some startScope) // We don't get the scope marks quite right for dtree-bound variables. This is because // we effectively lose an EndLocalScope for all dtrees that go to the same target // So we just pretend that the variable goes out of scope here. @@ -5267,11 +5591,11 @@ and GetTarget (targets:_[]) n = /// If inplabOpt is present, this label must get set to the first logical place to execute. /// For example, if no variables get bound this can just be set to jump straight to the target. and GenDecisionTreeSuccess cenv cgbuf inplabOpt stackAtTargets eenv es targetIdx targets (targetNext: int ref, targetCounts: Dictionary) repeatSP targetInfos sequel = - let (TTarget(vs, successExpr, spTarget)) = GetTarget targets targetIdx + let (TTarget(vs, successExpr, spTarget, flags)) = GetTarget targets targetIdx match IntMap.tryFind targetIdx targetInfos with | Some (targetInfo, isTargetPostponed) -> - let (targetMarkBeforeBinds, targetMarkAfterBinds: Mark, eenvAtTarget, _, _, _, _, _, _, _) = targetInfo + let (targetMarkBeforeBinds, targetMarkAfterBinds: Mark, eenvAtTarget, _, _, _, _, _, _, _, _) = targetInfo // We have encountered this target before. See if we should generate it now let targetCount = targetCounts.[targetIdx] @@ -5289,6 +5613,7 @@ and GenDecisionTreeSuccess cenv cgbuf inplabOpt stackAtTargets eenv es targetIdx (vs, es) ||> List.iter2 (fun v e -> + GetStoreValCtxt cenv cgbuf eenvAtTarget v // Emit the expression GenBindingRhs cenv cgbuf eenv SPSuppress v e) @@ -5317,9 +5642,16 @@ and GenDecisionTreeSuccess cenv cgbuf inplabOpt stackAtTargets eenv es targetIdx let targetMarkBeforeBinds = CG.GenerateDelayMark cgbuf "targetBeforeBinds" let targetMarkAfterBinds = CG.GenerateDelayMark cgbuf "targetAfterBinds" let startScope, endScope as scopeMarks = StartDelayedLocalScope "targetBinds" cgbuf - let binds = mkInvisibleBinds vs es + // Allocate storage for variables (except those lifted to be state machine variables) + let binds = + match flags with + | None -> mkInvisibleBinds vs es + | Some stateVarFlags -> + (vs, es, stateVarFlags) + |||> List.zip3 + |> List.choose (fun (v, e, flag) -> if flag then None else Some (mkInvisibleBind v e)) let eenvAtTarget = AllocStorageForBinds cenv cgbuf scopeMarks eenv binds - let targetInfo = (targetMarkBeforeBinds, targetMarkAfterBinds, eenvAtTarget, successExpr, spTarget, repeatSP, vs, binds, startScope, endScope) + let targetInfo = (targetMarkBeforeBinds, targetMarkAfterBinds, eenvAtTarget, successExpr, spTarget, repeatSP, vs, es, flags, startScope, endScope) let targetCount = targetCounts.[targetIdx] @@ -5344,7 +5676,8 @@ and GenDecisionTreeSuccess cenv cgbuf inplabOpt stackAtTargets eenv es targetIdx let targetInfos = IntMap.add targetIdx (targetInfo, isTargetPostponed) targetInfos targetInfos, genTargetInfoOpt -and GenDecisionTreeTarget cenv cgbuf stackAtTargets (targetMarkBeforeBinds, targetMarkAfterBinds, eenvAtTarget, successExpr, spTarget, repeatSP, vs, binds, startScope, endScope) sequel = +and GenDecisionTreeTarget cenv cgbuf stackAtTargets targetInfo sequel = + let (targetMarkBeforeBinds, targetMarkAfterBinds, eenvAtTarget, successExpr, spTarget, repeatSP, vs, es, flags, startScope, endScope) = targetInfo CG.SetMarkToHere cgbuf targetMarkBeforeBinds let spExpr = (match spTarget with DebugPointForTarget.Yes -> SPAlways | DebugPointForTarget.No _ -> SPSuppress) @@ -5362,7 +5695,8 @@ and GenDecisionTreeTarget cenv cgbuf stackAtTargets (targetMarkBeforeBinds, targ | DebugPointForTarget.No -> cgbuf.EmitStartOfHiddenCode() CG.SetMarkToHere cgbuf startScope - GenBindings cenv cgbuf eenvAtTarget binds + let binds = mkInvisibleBinds vs es + GenBindings cenv cgbuf eenvAtTarget binds flags CG.SetMarkToHere cgbuf targetMarkAfterBinds CG.SetStack cgbuf stackAtTargets (eenvAtTarget, spExpr, successExpr, (EndLocalScope(sequel, endScope))) @@ -5377,7 +5711,7 @@ and GenDecisionTreeSwitch cenv cgbuf inplabOpt stackAtTargets eenv e cases defau // optimize a test against a boolean value, i.e. the all-important if-then-else | TCase(DecisionTreeTest.Const(Const.Bool b), successTree) :: _ -> let failureTree = (match defaultTargetOpt with None -> cases.Tail.Head.CaseTree | Some d -> d) - GenDecisionTreeTest cenv eenv.cloc cgbuf stackAtTargets e None eenv (if b then successTree else failureTree) (if b then failureTree else successTree) targets targetCounts repeatSP targetInfos sequel contf + GenDecisionTreeTest cenv eenv.cloc cgbuf stackAtTargets e None false eenv (if b then successTree else failureTree) (if b then failureTree else successTree) targets targetCounts repeatSP targetInfos sequel contf // // Remove a single test for a union case . Union case tests are always exa //| [ TCase(DecisionTreeTest.UnionCase _, successTree) ] when (defaultTargetOpt.IsNone) -> @@ -5395,7 +5729,18 @@ and GenDecisionTreeSwitch cenv cgbuf inplabOpt stackAtTargets eenv e cases defau let idx = c.Index let avoidHelpers = entityRefInThisAssembly g.compilingFslib c.TyconRef let tester = (Some (pop 1, Push [g.ilg.typ_Bool], Choice1Of2 (avoidHelpers, cuspec, idx))) - GenDecisionTreeTest cenv eenv.cloc cgbuf stackAtTargets e tester eenv successTree failureTree targets targetCounts repeatSP targetInfos sequel contf + GenDecisionTreeTest cenv eenv.cloc cgbuf stackAtTargets e tester false eenv successTree failureTree targets targetCounts repeatSP targetInfos sequel contf + + // Use GenDecisionTreeTest to generate a single test for null (when no box required) where the success + // is going to the immediate first node in the tree + | TCase(DecisionTreeTest.IsNull _, (TDSuccess([], 0) as successTree)) :: rest + when rest.Length = (match defaultTargetOpt with None -> 1 | Some _ -> 0) + && not (isTyparTy g (tyOfExpr g e)) -> + let failureTree = + match defaultTargetOpt with + | None -> rest.Head.CaseTree + | Some tg -> tg + GenDecisionTreeTest cenv eenv.cloc cgbuf stackAtTargets e None true eenv successTree failureTree targets targetCounts repeatSP targetInfos sequel contf | _ -> let caseLabels = List.map (fun _ -> CG.GenerateDelayMark cgbuf "switch_case") cases @@ -5413,7 +5758,7 @@ and GenDecisionTreeSwitch cenv cgbuf inplabOpt stackAtTargets eenv e cases defau | DecisionTreeTest.Const(Const.Zero) -> GenExpr cenv cgbuf eenv SPSuppress e Continue BI_brfalse - | DecisionTreeTest.IsNull -> + | DecisionTreeTest.IsNull -> GenExpr cenv cgbuf eenv SPSuppress e Continue let srcTy = tyOfExpr g e if isTyparTy g srcTy then @@ -5508,7 +5853,7 @@ and GenDecisionTreeCases cenv cgbuf stackAtTargets eenv defaultTargetOpt targets // Used for the peephole optimization below and (|BoolExpr|_|) = function Expr.Const (Const.Bool b1, _, _) -> Some b1 | _ -> None -and GenDecisionTreeTest cenv cloc cgbuf stackAtTargets e tester eenv successTree failureTree targets targetCounts repeatSP targetInfos sequel contf = +and GenDecisionTreeTest cenv cloc cgbuf stackAtTargets e tester isNullTest eenv successTree failureTree targets targetCounts repeatSP targetInfos sequel contf = let g = cenv.g match successTree, failureTree with @@ -5516,14 +5861,15 @@ and GenDecisionTreeTest cenv cloc cgbuf stackAtTargets e tester eenv successTree // This comes up in the generated equality functions. REVIEW: do this as a peephole optimization elsewhere | TDSuccess(es1, n1), TDSuccess(es2, n2) when + not isNullTest && isNil es1 && isNil es2 && (match GetTarget targets n1, GetTarget targets n2 with - | TTarget(_, BoolExpr b1, _), TTarget(_, BoolExpr b2, _) -> b1 = not b2 + | TTarget(_, BoolExpr b1, _, _), TTarget(_, BoolExpr b2, _, _) -> b1 = not b2 | _ -> false) -> match GetTarget targets n1, GetTarget targets n2 with - | TTarget(_, BoolExpr b1, _), _ -> + | TTarget(_, BoolExpr b1, _, _), _ -> GenExpr cenv cgbuf eenv SPSuppress e Continue match tester with | Some (pops, pushes, i) -> @@ -5541,7 +5887,8 @@ and GenDecisionTreeTest cenv cloc cgbuf stackAtTargets e tester eenv successTree | _ -> match tester with - | None _ -> + | None -> + // Check if there is more logic in the decision tree for the failure branch // (and no more logic for the success branch), for example // when emitting the first part of 'expr1 || expr2'. @@ -5553,7 +5900,8 @@ and GenDecisionTreeTest cenv cloc cgbuf stackAtTargets e tester eenv successTree // OK, there is more logic in the decision tree on the failure branch let success = CG.GenerateDelayMark cgbuf "testSuccess" - GenExpr cenv cgbuf eenv SPSuppress e (CmpThenBrOrContinue(pop 1, [ I_brcmp (BI_brtrue, success.CodeLabel) ])) + let testForSuccess = if isNullTest then BI_brfalse else BI_brtrue + GenExpr cenv cgbuf eenv SPSuppress e (CmpThenBrOrContinue(pop 1, [ I_brcmp (testForSuccess, success.CodeLabel) ])) GenDecisionTreeAndTargetsInner cenv cgbuf None stackAtTargets eenv failureTree targets targetCounts repeatSP targetInfos sequel (fun targetInfos -> GenDecisionTreeAndTargetsInner cenv cgbuf (Some success) stackAtTargets eenv successTree targets targetCounts repeatSP targetInfos sequel contf ) @@ -5564,7 +5912,8 @@ and GenDecisionTreeTest cenv cloc cgbuf stackAtTargets e tester eenv successTree // in the decision tree on the failure branch. Continue doing the success branch // logic first. let failure = CG.GenerateDelayMark cgbuf "testFailure" - GenExpr cenv cgbuf eenv SPSuppress e (CmpThenBrOrContinue(pop 1, [ I_brcmp (BI_brfalse, failure.CodeLabel) ])) + let testForFailure = if isNullTest then BI_brtrue else BI_brfalse + GenExpr cenv cgbuf eenv SPSuppress e (CmpThenBrOrContinue(pop 1, [ I_brcmp (testForFailure, failure.CodeLabel) ])) GenDecisionTreeAndTargetsInner cenv cgbuf None stackAtTargets eenv successTree targets targetCounts repeatSP targetInfos sequel (fun targetInfos -> GenDecisionTreeAndTargetsInner cenv cgbuf (Some failure) stackAtTargets eenv failureTree targets targetCounts repeatSP targetInfos sequel contf ) @@ -5617,7 +5966,7 @@ and GenLetRecBindings cenv (cgbuf: CodeGenBuffer) eenv (allBinds: Bindings, m) = let isLocalTypeFunc = Option.isSome thisVars && (IsNamedLocalTypeFuncVal cenv.g (Option.get thisVars) e) let thisVars = (match e with Expr.Obj _ -> [] | _ when isLocalTypeFunc -> [] | _ -> Option.map mkLocalValRef thisVars |> Option.toList) let canUseStaticField = (match e with Expr.Obj _ -> false | _ -> true) - let clo, _, eenvclo = GetIlxClosureInfo cenv m isLocalTypeFunc canUseStaticField thisVars {eenv with letBoundVars=(mkLocalValRef boundv) :: eenv.letBoundVars} e + let clo, _, eenvclo = GetIlxClosureInfo cenv m ILBoxity.AsObject isLocalTypeFunc canUseStaticField thisVars {eenv with letBoundVars=(mkLocalValRef boundv) :: eenv.letBoundVars} e clo.cloFreeVars |> List.iter (fun fv -> if Zset.contains fv forwardReferenceSet then match StorageForVal cenv.g m fv eenvclo with @@ -5647,7 +5996,7 @@ and GenLetRecBindings cenv (cgbuf: CodeGenBuffer) eenv (allBinds: Bindings, m) = // Generate the actual bindings let _ = (recursiveVars, allBinds) ||> List.fold (fun forwardReferenceSet (bind: Binding) -> - GenBinding cenv cgbuf eenv bind + GenBinding cenv cgbuf eenv bind false // Record the variable as defined let forwardReferenceSet = Zset.remove bind.Var forwardReferenceSet // Execute and discard any fixups that can now be committed @@ -5670,9 +6019,9 @@ and GenDebugPointForBind cenv cgbuf bind = pt |> Option.iter (CG.EmitSeqPoint cgbuf) sp -and GenBinding cenv cgbuf eenv bind = +and GenBinding cenv cgbuf eenv (bind: Binding) (isStateVar: bool) = let sp = GenDebugPointForBind cenv cgbuf bind - GenBindingAfterDebugPoint cenv cgbuf eenv sp bind None + GenBindingAfterDebugPoint cenv cgbuf eenv sp bind isStateVar None and ComputeMemberAccessRestrictedBySig eenv vspec = let isHidden = @@ -5688,17 +6037,19 @@ and ComputeMethodAccessRestrictedBySig eenv vspec = vspec.IsIncrClassGeneratedMember // compiler generated members for class function 'let' bindings get assembly visibility ComputeMemberAccess isHidden -and GenBindingAfterDebugPoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) startScopeMarkOpt = +and GenBindingAfterDebugPoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) isStateVar startScopeMarkOpt = let g = cenv.g // Record the closed reflection definition if publishing // There is no real reason we're doing this so late in the day match vspec.PublicPath, vspec.ReflectedDefinition with - | Some _, Some e -> cgbuf.mgbuf.AddReflectedDefinition(vspec, e) + | Some _, Some e when not isStateVar -> cgbuf.mgbuf.AddReflectedDefinition(vspec, e) | _ -> () - let eenv = { eenv with letBoundVars = (mkLocalValRef vspec) :: eenv.letBoundVars; - initLocals = eenv.initLocals && (match vspec.ApparentEnclosingEntity with Parent ref -> not (HasFSharpAttribute g g.attrib_SkipLocalsInitAttribute ref.Attribs) | _ -> true) } + let eenv = + if isStateVar then eenv + else { eenv with letBoundVars = (mkLocalValRef vspec) :: eenv.letBoundVars; + initLocals = eenv.initLocals && (match vspec.ApparentEnclosingEntity with Parent ref -> not (HasFSharpAttribute g g.attrib_SkipLocalsInitAttribute ref.Attribs) | _ -> true) } let access = ComputeMethodAccessRestrictedBySig eenv vspec @@ -5719,13 +6070,13 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) star CommitStartScope cgbuf startScopeMarkOpt // The initialization code for static 'let' and 'do' bindings gets compiled into the initialization .cctor for the whole file - | _ when vspec.IsClassConstructor && isNil vspec.TopValDeclaringEntity.TyparsNoRange -> + | _ when vspec.IsClassConstructor && isNil vspec.TopValDeclaringEntity.TyparsNoRange && not isStateVar -> let tps, _, _, _, cctorBody, _ = IteratedAdjustArityOfLambda g cenv.amap vspec.ValReprInfo.Value rhsExpr let eenv = EnvForTypars tps eenv CommitStartScope cgbuf startScopeMarkOpt GenExpr cenv cgbuf eenv SPSuppress cctorBody discard - - | Method (topValInfo, _, mspec, mspecW, _, ctps, mtps, curriedArgInfos, paramInfos, witnessInfos, argTys, retInfo) -> + + | Method (topValInfo, _, mspec, mspecW, _, ctps, mtps, curriedArgInfos, paramInfos, witnessInfos, argTys, retInfo) when not isStateVar -> let methLambdaTypars, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaCurriedVars, methLambdaBody, methLambdaBodyTy = IteratedAdjustArityOfLambda g cenv.amap topValInfo rhsExpr @@ -5745,7 +6096,7 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) star let copyOfLambdaBody = copyExpr cenv.g CloneAll methLambdaBody generator cenv cgbuf.mgbuf eenv (vspec, mspecW, hasWitnessEntry, true, access, ctps, mtps, witnessInfos, curriedArgInfos, paramInfos, argTys, retInfo, topValInfo, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaTypars, methLambdaVars, copyOfLambdaBody, methLambdaBodyTy) - | StaticProperty (ilGetterMethSpec, optShadowLocal) -> + | StaticProperty (ilGetterMethSpec, optShadowLocal) when not isStateVar -> let ilAttribs = GenAttrs cenv eenv vspec.Attribs let ilTy = ilGetterMethSpec.FormalReturnType @@ -5862,10 +6213,17 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) star | Local (_, realloc, _), Expr.Const (Const.Zero, _, _) when not realloc && not (eenv.isInLoop && vspec.IsMutable) -> CommitStartScope cgbuf startScopeMarkOpt | _ -> + GetStoreValCtxt cenv cgbuf eenv vspec GenBindingRhs cenv cgbuf eenv SPSuppress vspec rhsExpr CommitStartScope cgbuf startScopeMarkOpt GenStoreVal cenv cgbuf eenv vspec.Range vspec +and GetStoreValCtxt cenv cgbuf eenv (vspec: Val) = + // Emit the ldarg0 if needed + match StorageForVal cenv.g vspec.Range vspec eenv with + | Env (ilCloTy, _, _) -> CG.EmitInstr cgbuf (pop 0) (Push [ilCloTy]) mkLdarg0 + | _ -> () + //------------------------------------------------------------------------- // Generate method bindings //------------------------------------------------------------------------- @@ -6215,9 +6573,6 @@ and ComputeMethodImplAttribs cenv (_v: Val) attrs = let hasAggressiveInliningImplFlag = (implflags &&& 0x0100) <> 0x0 hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningImplFlag, hasAggressiveInliningImplFlag, attrs -and DelayGenMethodForBinding cenv mgbuf eenv ilxMethInfoArgs = - cenv.delayedGenMethods.Enqueue (fun cenv -> GenMethodForBinding cenv mgbuf eenv ilxMethInfoArgs) - and GenMethodForBinding cenv mgbuf eenv (v: Val, mspec, hasWitnessEntry, generateWitnessArgs, access, ctps, mtps, witnessInfos, curriedArgInfos, paramInfos, argTys, retInfo, topValInfo, @@ -6548,8 +6903,13 @@ and GenPInvokeMethod (nm, dll, namedArgs) = ThrowOnUnmappableChar= if (decoder.FindBool "ThrowOnUnmappableChar" false) then PInvokeThrowOnUnmappableChar.Enabled else PInvokeThrowOnUnmappableChar.UseAssembly CharBestFit=if (decoder.FindBool "BestFitMapping" false) then PInvokeCharBestFit.Enabled else PInvokeCharBestFit.UseAssembly } : PInvokeMethod MethodBody.PInvoke(lazy pinvoke) - -and GenBindings cenv cgbuf eenv binds = List.iter (GenBinding cenv cgbuf eenv) binds + +and GenBindings cenv cgbuf eenv binds flags = + match flags with + | None -> + binds |> List.iter (fun bind -> GenBinding cenv cgbuf eenv bind false) + | Some flags -> + (binds, flags) ||> List.iter2 (fun bind flag -> GenBinding cenv cgbuf eenv bind flag) //------------------------------------------------------------------------- // Generate locals and other storage of values @@ -6557,11 +6917,7 @@ and GenBindings cenv cgbuf eenv binds = List.iter (GenBinding cenv cgbuf eenv) b and GenSetVal cenv cgbuf eenv (vref, e, m) sequel = let storage = StorageForValRef cenv.g m vref eenv - match storage with - | Env (ilCloTy, _, _) -> - CG.EmitInstr cgbuf (pop 0) (Push [ilCloTy]) mkLdarg0 - | _ -> - () + GetStoreValCtxt cenv cgbuf eenv vref.Deref GenExpr cenv cgbuf eenv SPSuppress e Continue GenSetStorage vref.Range cgbuf storage GenUnitThenSequel cenv eenv m eenv.cloc cgbuf sequel @@ -6719,7 +7075,7 @@ and GenStoreVal cenv cgbuf eenv m (vspec: Val) = GenSetStorage vspec.Range cgbuf (StorageForVal cenv.g m vspec eenv) /// Allocate IL locals -and AllocLocal cenv cgbuf eenv compgen (v, ty, isFixed) (scopeMarks: Mark * Mark) = +and AllocLocal cenv cgbuf eenv compgen (v, ty, isFixed) (scopeMarks: Mark * Mark) : int * _ * _ = // The debug range for the local let ranges = if compgen then [] else [(v, scopeMarks)] // Get an index for the local @@ -6745,7 +7101,7 @@ and AllocLocalVal cenv cgbuf v eenv repr scopeMarks = let eenvinner = {eenv with letBoundVars=(mkLocalValRef v) :: eenv.letBoundVars} - let cloinfo, _, _ = GetIlxClosureInfo cenv v.Range true true [] eenvinner r + let cloinfo, _, _ = GetIlxClosureInfo cenv v.Range ILBoxity.AsObject true true [] eenvinner r cloinfo let idx, realloc, eenv = AllocLocal cenv cgbuf eenv v.IsCompilerGenerated (v.CompiledName g.CompilerGlobalState, g.ilg.typ_Object, false) scopeMarks @@ -7021,7 +7377,7 @@ and GenModuleDef cenv (cgbuf: CodeGenBuffer) qname lazyInitInfo eenv x = mbinds |> List.iter (GenModuleBinding cenv cgbuf qname lazyInitInfo eenv m) | TMDefLet(bind, _) -> - GenBindings cenv cgbuf eenv [bind] + GenBindings cenv cgbuf eenv [bind] None | TMDefDo(e, _) -> GenExpr cenv cgbuf eenv SPAlways e discard @@ -7394,7 +7750,7 @@ and GenTypeDef cenv mgbuf lazyInitInfo eenv m (tycon: Tycon) = | TNoRepr -> () | TAsmRepr _ | TILObjectRepr _ | TMeasureableRepr _ -> () | TFSharpObjectRepr _ | TRecdRepr _ | TUnionRepr _ -> - let eenvinner = ReplaceTyenv (TypeReprEnv.ForTycon tycon) eenv + let eenvinner = EnvForTycon tycon eenv let thisTy = generalizedTyconRef tcref let ilThisTy = GenType cenv.amap m eenvinner.tyenv thisTy @@ -8125,6 +8481,7 @@ let GetEmptyIlxGenEnv (g: TcGlobals) ccu = let thisCompLoc = CompLocForCcu ccu { tyenv=TypeReprEnv.Empty cloc = thisCompLoc + exitSequel = Return valsInScope=ValMap<_>.Empty witnessesInScope = EmptyTraitWitnessInfoHashMap g suppressWitnesses = false diff --git a/src/fsharp/InnerLambdasToTopLevelFuncs.fs b/src/fsharp/InnerLambdasToTopLevelFuncs.fs index fb070b66176..6b08832a7e0 100644 --- a/src/fsharp/InnerLambdasToTopLevelFuncs.fs +++ b/src/fsharp/InnerLambdasToTopLevelFuncs.fs @@ -137,7 +137,7 @@ let mkLocalNameTypeArity compgen m name ty topValInfo = let GetValsBoundUnderMustInline xinfo = let accRejectFrom (v: Val) repr rejectS = - if v.InlineInfo = ValInline.PseudoVal then + if v.InlineInfo = ValInline.Always then Zset.union (GetValsBoundInExpr repr) rejectS else rejectS let rejectS = Zset.empty valOrder @@ -157,7 +157,9 @@ let IsRefusedTLR g (f: Val) = // Special values are instance methods etc. on .NET types. For now leave these alone let specialVal = f.MemberInfo.IsSome let alreadyChosen = f.ValReprInfo.IsSome - let refuseTest = alreadyChosen || mutableVal || byrefVal || specialVal || dllImportStubOrOtherNeverInline + let isResumableCode = isReturnsResumableCodeTy g f.Type + let isInlineIfLambda = f.InlineIfLambda + let refuseTest = alreadyChosen || mutableVal || byrefVal || specialVal || dllImportStubOrOtherNeverInline || isResumableCode || isInlineIfLambda refuseTest let IsMandatoryTopLevel (f: Val) = @@ -1131,7 +1133,7 @@ module Pass4_RewriteAssembly = // ilobj - has implicit lambda exprs and recursive/base references | Expr.Obj (_, ty, basev, basecall, overrides, iimpls, m) -> - let basecall, z = TransExpr penv z basecall + let basecall, z = TransExpr penv z basecall let overrides, z = List.mapFold (TransMethod penv) z overrides let iimpls, z = (z, iimpls) ||> List.mapFold (fun z (tType, objExprs) -> @@ -1291,11 +1293,11 @@ module Pass4_RewriteAssembly = let dflt, z = Option.mapFold (TransDecisionTree penv) z dflt TDSwitch (e, cases, dflt, m), z - and TransDecisionTreeTarget penv z (TTarget(vs, e, spTarget)) = + and TransDecisionTreeTarget penv z (TTarget(vs, e, spTarget, flags)) = let z = EnterInner z let e, z = TransExpr penv z e let z = ExitInner z - TTarget(vs, e, spTarget), z + TTarget(vs, e, spTarget, flags), z and TransValBinding penv z bind = TransBindingRhs penv z bind and TransValBindings penv z binds = List.mapFold (TransValBinding penv) z binds diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index 2e7fd7f4af9..c852582a5b7 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -29,6 +29,7 @@ type LanguageFeature = | FromEndSlicing | FixedIndexSlice3d4d | AndBang + | ResumableStateMachines | NullableOptionalInterop | DefaultInterfaceMemberConsumption | WitnessPassing @@ -82,6 +83,7 @@ type LanguageVersion (specifiedVersionAsString) = LanguageFeature.OverloadsForCustomOperations, previewVersion LanguageFeature.ExpandedMeasurables, previewVersion LanguageFeature.FromEndSlicing, previewVersion + LanguageFeature.ResumableStateMachines, previewVersion LanguageFeature.StructActivePattern, previewVersion LanguageFeature.PrintfBinaryFormat, previewVersion LanguageFeature.UseBindingValueDiscard, previewVersion @@ -153,6 +155,7 @@ type LanguageVersion (specifiedVersionAsString) = | LanguageFeature.FromEndSlicing -> FSComp.SR.featureFromEndSlicing() | LanguageFeature.FixedIndexSlice3d4d -> FSComp.SR.featureFixedIndexSlice3d4d() | LanguageFeature.AndBang -> FSComp.SR.featureAndBang() + | LanguageFeature.ResumableStateMachines -> FSComp.SR.featureResumableStateMachines() | LanguageFeature.NullableOptionalInterop -> FSComp.SR.featureNullableOptionalInterop() | LanguageFeature.DefaultInterfaceMemberConsumption -> FSComp.SR.featureDefaultInterfaceMemberConsumption() | LanguageFeature.WitnessPassing -> FSComp.SR.featureWitnessPassing() diff --git a/src/fsharp/LanguageFeatures.fsi b/src/fsharp/LanguageFeatures.fsi index e7e0a9c12a9..b7ee7c18f7a 100644 --- a/src/fsharp/LanguageFeatures.fsi +++ b/src/fsharp/LanguageFeatures.fsi @@ -17,6 +17,7 @@ type LanguageFeature = | FromEndSlicing | FixedIndexSlice3d4d | AndBang + | ResumableStateMachines | NullableOptionalInterop | DefaultInterfaceMemberConsumption | WitnessPassing diff --git a/src/fsharp/LowerCallsAndSeqs.fs b/src/fsharp/LowerCallsAndSeqs.fs index 3acc080f9b9..9ef6657dbe5 100644 --- a/src/fsharp/LowerCallsAndSeqs.fs +++ b/src/fsharp/LowerCallsAndSeqs.fs @@ -229,55 +229,55 @@ let (|SeqElemTy|_|) g amap m ty = /// expressions: one for 'MoveNext' and one for 'Dispose'. let ConvertSequenceExprToObject g amap overallExpr = /// Implement a decision to represent a 'let' binding as a non-escaping local variable (rather than a state machine variable) - let RepresentBindingAsLocal (bind: Binding) res2 m = + let RepresentBindingAsLocal (bind: Binding) resBody m = if verbose then printfn "LowerSeq: found local variable %s" bind.Var.DisplayName - { res2 with + { resBody with phase2 = (fun ctxt -> - let generate2, dispose2, checkDispose2 = res2.phase2 ctxt - let generate = mkLetBind m bind generate2 - let dispose = dispose2 - let checkDispose = checkDispose2 + let generateBody, disposeBody, checkDisposeBody = resBody.phase2 ctxt + let generate = mkLetBind m bind generateBody + let dispose = disposeBody + let checkDispose = checkDisposeBody generate, dispose, checkDispose) - stateVars = res2.stateVars } + stateVars = resBody.stateVars } /// Implement a decision to represent a 'let' binding as a state machine variable - let RepresentBindingAsStateMachineLocal (bind: Binding) res2 m = + let RepresentBindingAsStateMachineLocal (bind: Binding) resBody m = if verbose then printfn "LowerSeq: found state variable %s" bind.Var.DisplayName let (TBind(v, e, sp)) = bind let sp, spm = match sp with - | DebugPointAtBinding.Yes m -> DebugPointAtSequential.Both, m - | _ -> DebugPointAtSequential.StmtOnly, e.Range + | DebugPointAtBinding.Yes m -> DebugPointAtSequential.SuppressNeither, m + | _ -> DebugPointAtSequential.SuppressStmt, e.Range let vref = mkLocalValRef v - { res2 with + { resBody with phase2 = (fun ctxt -> - let generate2, dispose2, checkDispose2 = res2.phase2 ctxt + let generateBody, disposeBody, checkDisposeBody = resBody.phase2 ctxt let generate = mkCompGenSequential m (mkSequential sp m (mkValSet spm vref e) - generate2) + generateBody) // zero out the current value to free up its memory (mkValSet m vref (mkDefault (m, vref.Type))) - let dispose = dispose2 - let checkDispose = checkDispose2 + let dispose = disposeBody + let checkDispose = checkDisposeBody generate, dispose, checkDispose) - stateVars = vref :: res2.stateVars } + stateVars = vref :: resBody.stateVars } - let RepresentBindingsAsLifted mkBinds res2 = + let RepresentBindingsAsLifted mkBinds resBody = if verbose then printfn "found top level let " - { res2 with + { resBody with phase2 = (fun ctxt -> - let generate2, dispose2, checkDispose2 = res2.phase2 ctxt - let generate = mkBinds generate2 - let dispose = dispose2 - let checkDispose = checkDispose2 + let generateBody, disposeBody, checkDisposeBody = resBody.phase2 ctxt + let generate = mkBinds generateBody + let dispose = disposeBody + let checkDispose = checkDisposeBody generate, dispose, checkDispose) } let rec ConvertSeqExprCode @@ -297,7 +297,7 @@ let ConvertSequenceExprToObject g amap overallExpr = let label = IL.generateCodeLabel() Some { phase2 = (fun (pcVar, currVar, _nextv, pcMap) -> let generate = - mkSequential DebugPointAtSequential.Both m + mkSequential DebugPointAtSequential.SuppressNeither m (mkValSet m pcVar (mkInt32 g m pcMap.[label])) (mkCompGenSequential m (mkValSet m currVar e) @@ -339,7 +339,7 @@ let ConvertSequenceExprToObject g amap overallExpr = Some { phase2 = (fun ctxt -> let generate1, dispose1, checkDispose1 = res1.phase2 ctxt let generate2, dispose2, checkDispose2 = res2.phase2 ctxt - let generate = mkSequential DebugPointAtSequential.Both m generate1 generate2 + let generate = mkSequential DebugPointAtSequential.SuppressNeither m generate1 generate2 // Order shouldn't matter here, since disposals actions are linked together by goto's (each ends in a goto). // However leaving as is for now. let dispose = mkCompGenSequential m dispose2 dispose1 @@ -416,7 +416,7 @@ let ConvertSequenceExprToObject g amap overallExpr = let compensation = copyExpr g CloneAllAndMarkExprValsAsCompilerGenerated compensation mkCompGenSequential m // set the PC to the inner finally, so that if an exception happens we run the right finally - (mkSequential DebugPointAtSequential.StmtOnly m + (mkSequential DebugPointAtSequential.SuppressStmt m (mkValSet mTry pcVar (mkInt32 g m pcMap.[innerDisposeContinuationLabel])) generate1 ) // set the PC past the try/finally before trying to run it, to make sure we only run it once @@ -430,7 +430,7 @@ let ConvertSequenceExprToObject g amap overallExpr = dispose1 // set the PC past the try/finally before trying to run it, to make sure we only run it once (mkLabelled m innerDisposeContinuationLabel - (mkSequential DebugPointAtSequential.StmtOnly m + (mkSequential DebugPointAtSequential.SuppressStmt m (mkValSet mFinally pcVar (mkInt32 g m pcMap.[currentDisposeContinuationLabel])) (mkCompGenSequential m compensation @@ -478,17 +478,17 @@ let ConvertSequenceExprToObject g amap overallExpr = // Restriction: compilation of sequence expressions containing non-toplevel constrained generic functions is not supported when bind.Var.IsCompiledAsTopLevel || not (IsGenericValWithGenericConstraints g bind.Var) -> - let resBody = ConvertSeqExprCode false isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel bodyExpr - match resBody with - | Some res2 -> + let resBodyOpt = ConvertSeqExprCode false isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel bodyExpr + match resBodyOpt with + | Some resBody -> if bind.Var.IsCompiledAsTopLevel then - Some (RepresentBindingsAsLifted (mkLetBind m bind) res2) - elif not (res2.asyncVars.FreeLocals.Contains(bind.Var)) then + Some (RepresentBindingsAsLifted (mkLetBind m bind) resBody) + elif not (resBody.asyncVars.FreeLocals.Contains(bind.Var)) then // printfn "found state variable %s" bind.Var.DisplayName - Some (RepresentBindingAsLocal bind res2 m) + Some (RepresentBindingAsLocal bind resBody m) else // printfn "found state variable %s" bind.Var.DisplayName - Some (RepresentBindingAsStateMachineLocal bind res2 m) + Some (RepresentBindingAsStateMachineLocal bind resBody m) | None -> None @@ -526,31 +526,33 @@ let ConvertSequenceExprToObject g amap overallExpr = // transferred to the r.h.s. are not yet compiled. // // TODO: remove this limitation - | Expr.Match (spBind, exprm, pt, targets, m, ty) when targets |> Array.forall (fun (TTarget(vs, _e, _spTarget)) -> isNil vs) -> - // lower all the targets. abandon if any fail to lower + | Expr.Match (spBind, exprm, pt, targets, m, ty) -> // lower all the targets. abandon if any fail to lower - let tglArray = targets |> Array.map (fun (TTarget(_vs, targetExpr, _spTarget)) -> ConvertSeqExprCode false isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel targetExpr) + let tglArray = targets |> Array.map (fun (TTarget(_vs, targetExpr, _spTarget, _)) -> ConvertSeqExprCode false isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel targetExpr) if tglArray |> Array.forall Option.isSome then let tglArray = Array.map Option.get tglArray let tgl = Array.toList tglArray let labs = tgl |> List.collect (fun res -> res.entryPoints) - let (asyncVars, _) = - ((emptyFreeVars, false), Array.zip targets tglArray) - ||> Array.fold (fun (fvs, seenLabel) ((TTarget(_vs, e, _spTarget)), res) -> - if seenLabel then unionFreeVars fvs (freeInExpr CollectLocals e), true - else res.asyncVars, not res.entryPoints.IsEmpty) + let asyncVars = + (emptyFreeVars, Array.zip targets tglArray) + ||> Array.fold (fun fvs ((TTarget(_vs, _, _spTarget, _)), res) -> + if res.entryPoints.IsEmpty then fvs else unionFreeVars fvs res.asyncVars) - let stateVars = tgl |> List.collect (fun res -> res.stateVars) + let stateVars = + (targets, tglArray) ||> Array.zip |> Array.toList |> List.collect (fun (TTarget(vs, _, _, _), res) -> + let stateVars = vs |> List.filter (fun v -> res.asyncVars.FreeLocals.Contains(v)) |> List.map mkLocalValRef + stateVars @ res.stateVars) let significantClose = tgl |> List.exists (fun res -> res.significantClose) Some { phase2 = (fun ctxt -> let gtgs, disposals, checkDisposes = (Array.toList targets, tgl) - ||> List.map2 (fun (TTarget(vs, _, spTarget)) res -> + ||> List.map2 (fun (TTarget(vs, _, spTarget, _)) res -> + let flags = vs |> List.map (fun v -> res.asyncVars.FreeLocals.Contains(v)) let generate, dispose, checkDispose = res.phase2 ctxt - let gtg = TTarget(vs, generate, spTarget) + let gtg = TTarget(vs, generate, spTarget, Some flags) gtg, dispose, checkDispose) |> List.unzip3 let generate = primMkMatch (spBind, exprm, pt, Array.ofList gtgs, m, ty) @@ -596,9 +598,9 @@ let ConvertSequenceExprToObject g amap overallExpr = let label = IL.generateCodeLabel() Some { phase2 = (fun (pcVar, _currv, nextVar, pcMap) -> let generate = - mkCompGenSequential m + mkSequential DebugPointAtSequential.SuppressStmt m (mkValSet m pcVar (mkInt32 g m pcMap.[label])) - (mkSequential DebugPointAtSequential.Both m + (mkCompGenSequential m (mkAddrSet m nextVar arbitrarySeqExpr) (mkCompGenSequential m (Expr.Op (TOp.Return, [], [mkTwo g m], m)) @@ -812,7 +814,6 @@ let ConvertSequenceExprToObject g amap overallExpr = None | _ -> None - /// Build the 'test and dispose' part of a 'use' statement let BuildDisposableCleanup tcVal (g: TcGlobals) infoReader m (v: Val) = let disposeMethod = @@ -873,7 +874,7 @@ let LowerComputedListOrArraySeqExpr tcVal g amap m collectorTy overallSeqExpr = let res2 = ConvertSeqExprCode false isTailcall e2 match res1, res2 with | Result.Ok (_, e1R), Result.Ok (closed2, e2R) -> - let exprR = mkSequential DebugPointAtSequential.Both m e1R e2R + let exprR = mkSequential DebugPointAtSequential.SuppressNeither m e1R e2R Result.Ok (closed2, exprR) | Result.Error msg, _ | _, Result.Error msg -> Result.Error msg @@ -958,10 +959,10 @@ let LowerComputedListOrArraySeqExpr tcVal g amap m collectorTy overallSeqExpr = | Expr.Match (spBind, exprm, pt, targets, m, ty) -> // lower all the targets. abandon if any fail to lower let resTargets = - targets |> Array.map (fun (TTarget(vs, targetExpr, spTarget)) -> + targets |> Array.map (fun (TTarget(vs, targetExpr, spTarget, flags)) -> match ConvertSeqExprCode false false targetExpr with | Result.Ok (_, targetExprR) -> - Result.Ok (TTarget(vs, targetExprR, spTarget)) + Result.Ok (TTarget(vs, targetExprR, spTarget, flags)) | Result.Error msg -> Result.Error msg ) if resTargets |> Array.forall (function Result.Ok _ -> true | _ -> false) then let tglArray = Array.map (function Result.Ok v -> v | _ -> failwith "unreachable") resTargets diff --git a/src/fsharp/LowerCallsAndSeqs.fsi b/src/fsharp/LowerCallsAndSeqs.fsi index 10a5e26550a..f676fdc7533 100644 --- a/src/fsharp/LowerCallsAndSeqs.fsi +++ b/src/fsharp/LowerCallsAndSeqs.fsi @@ -22,6 +22,6 @@ val LowerImplFile: g: TcGlobals -> assembly: TypedImplFile -> TypedImplFile /// free variables of the sequence expression. val ConvertSequenceExprToObject: g: TcGlobals -> amap: ImportMap -> overallExpr: Expr -> (ValRef * ValRef * ValRef * ValRef list * Expr * Expr * Expr * TType * range) option -val IsPossibleSequenceExpr: g: TcGlobals -> overallExpr: Expr -> bool +val IsPossibleSequenceExpr: g: TcGlobals -> overallExpr: Expr -> bool val LowerComputedListOrArrayExpr: tcVal: ConstraintSolver.TcValF -> g: TcGlobals -> amap: ImportMap -> Expr -> Expr option diff --git a/src/fsharp/LowerStateMachines.fs b/src/fsharp/LowerStateMachines.fs new file mode 100644 index 00000000000..55043a19bdf --- /dev/null +++ b/src/fsharp/LowerStateMachines.fs @@ -0,0 +1,906 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module internal FSharp.Compiler.LowerStateMachines + +open Internal.Utilities.Collections +open Internal.Utilities.Library +open Internal.Utilities.Library.Extras +open FSharp.Compiler.AbstractIL +open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.ErrorLogger +open FSharp.Compiler.TcGlobals +open FSharp.Compiler.Syntax +open FSharp.Compiler.Syntax.PrettyNaming +open FSharp.Compiler.TypedTree +open FSharp.Compiler.TypedTreeBasics +open FSharp.Compiler.TypedTreeOps + +let mkLabelled m l e = mkCompGenSequential m (Expr.Op (TOp.Label l, [], [], m)) e + +type StateMachineConversionFirstPhaseResult = + { + /// Represents the expanded expression prior to decisions about labels + phase1: Expr + + /// The second phase of the transformation. It is run after all code labels and their mapping to program counters have been determined + /// after the first phase. + phase2: (Map -> Expr) + + /// The labels allocated for this portion of the computation + entryPoints: int list + + /// The state variables allocated for one portion of the sequence expression (i.e. the local let-bound variables which become state variables) + stateVars: ValRef list + + /// All this values get represented via the 'this' pointer + thisVars: ValRef list + + /// The vars captured by the non-synchronous resumable path + resumableVars: FreeVars + } + +#if DEBUG +let sm_verbose = try System.Environment.GetEnvironmentVariable("FSharp_StateMachineVerbose") <> null with _ -> false +#else +let sm_verbose = false +#endif + +let rec (|OptionalResumeAtExpr|) g expr = + match expr with + | IfUseResumableStateMachinesExpr g (OptionalResumeAtExpr g res, _) -> res + | Expr.Sequential(ResumeAtExpr g pcExpr, codeExpr, NormalSeq, _, _m) -> (Some pcExpr, codeExpr) + | _ -> (None, expr) + +/// Implement a decision to represent a 'let' binding as a non-escaping local variable (rather than a state machine variable) +let RepresentBindingAsTopLevelOrLocal (bind: Binding) (res2: StateMachineConversionFirstPhaseResult) m = + if sm_verbose then + printfn "LowerStateMachine: found local variable %s" bind.Var.DisplayName + + { res2 with + phase1 = mkLetBind m bind res2.phase1 + phase2 = (fun ctxt -> mkLetBind m bind (res2.phase2 ctxt)) } + +/// Implement a decision to represent a 'let' binding as the 'this' pointer of the state machine, +/// because it is rebinding the 'this' variable +let RepresentBindingAsThis (bind: Binding) (res2: StateMachineConversionFirstPhaseResult) _m = + if sm_verbose then + printfn "LowerStateMachine: found local variable %s" bind.Var.DisplayName + + { res2 with + thisVars = mkLocalValRef bind.Var :: res2.thisVars + // Drop the let binding on the floor as it is only rebinding the 'this' variable + phase1 = res2.phase1 + phase2 = res2.phase2 } + +/// Implement a decision to represent a 'let' binding as a state machine variable +let RepresentBindingAsStateVar g (bind: Binding) (resBody: StateMachineConversionFirstPhaseResult) m = + if sm_verbose then + printfn "LowerStateMachine: found state variable %s" bind.Var.DisplayName + + let (TBind(v, e, sp)) = bind + let sp, spm = + match sp with + | DebugPointAtBinding.Yes m -> DebugPointAtSequential.SuppressNeither, m + | _ -> DebugPointAtSequential.SuppressStmt, e.Range + let vref = mkLocalValRef v + { resBody with + phase1 = mkSequential sp m (mkValSet spm vref e) resBody.phase1 + phase2 = (fun ctxt -> + let generateBody = resBody.phase2 ctxt + let generate = + mkSequential sp m + (mkValSet spm vref e) + // Within all resumable code, a return value of 'true' indicates success/completion path, when we can clear + // state machine locals. + (if typeEquiv g (tyOfExpr g generateBody) g.bool_ty then + mkCond DebugPointAtBinding.NoneAtInvisible DebugPointForTarget.No m g.bool_ty generateBody + (mkCompGenSequential m + (mkValSet m vref (mkDefault (m, vref.Type))) + (mkTrue g m)) + (mkFalse g m) + else + generateBody) + generate ) + stateVars = vref :: resBody.stateVars } + +let isExpandVar g (v: Val) = + isReturnsResumableCodeTy g v.TauType && + not v.IsCompiledAsTopLevel + +// We allow a prefix of bindings prior to the state machine, e.g. +// task { .. } +// becomes +// let builder@ = task +// .... +let isStateMachineBindingVar g (v: Val) = + isExpandVar g v || + (let nm = v.LogicalName + (nm.StartsWith "builder@" + || (v.BaseOrThisInfo = MemberThisVal)) && + not v.IsCompiledAsTopLevel) + +type env = + { + ResumableCodeDefns: ValMap + TemplateStructTy: TType option + //MachineAddrExpr: Expr option + } + + static member Empty = + { ResumableCodeDefns = ValMap.Empty + TemplateStructTy = None + //MachineAddrExpr = None + } + +/// Detect prefix of expanded, optimized state machine expressions +/// This is run on every expression during codegen +let rec IsStateMachineExpr g overallExpr = + match overallExpr with + // 'let' binding of initial code + | Expr.Let (defn, bodyExpr, m, _) when isStateMachineBindingVar g defn.Var -> + match IsStateMachineExpr g bodyExpr with + | None -> None + | Some altExpr as r -> + match altExpr with + | None -> r + | Some e -> Some (Some (mkLetBind m defn e)) + // Recognise 'if __useResumableCode ...' + | IfUseResumableStateMachinesExpr g (thenExpr, elseExpr) -> + match IsStateMachineExpr g thenExpr with + | None -> None + | Some _ -> Some (Some elseExpr) + | StructStateMachineExpr g _ -> Some None + | _ -> None + +type LoweredStateMachine = + LoweredStateMachine of + templateStructTy: TType * + dataTy: TType * + stateVars: ValRef list * + thisVars: ValRef list * + moveNext: (Val * Expr) * + setStateMachine: (Val * Val * Expr) * + afterCode: (Val * Expr) + +type LoweredStateMachineResult = + /// A state machine was recognised and was compilable + | Lowered of LoweredStateMachine + + /// A state machine was recognised and was not compilable and an alternative is available + | UseAlternative of message: string * alternativeExpr: Expr + + /// A state machine was recognised and was not compilable and no alternative is available + | NoAlternative of message: string + + /// The construct was not a state machine + | NotAStateMachine + +/// Used to scope the action of lowering a state machine expression +type LowerStateMachine(g: TcGlobals) = + + let mutable pcCount = 0 + let genPC() = + pcCount <- pcCount + 1 + pcCount + + // Record definitions for any resumable code + let rec BindResumableCodeDefinitions (env: env) expr = + + match expr with + // Bind 'let __expand_ABC = bindExpr in bodyExpr' + | Expr.Let (defn, bodyExpr, _, _) when isStateMachineBindingVar g defn.Var -> + if sm_verbose then printfn "binding %A --> %A..." defn.Var defn.Expr + let envR = { env with ResumableCodeDefns = env.ResumableCodeDefns.Add defn.Var defn.Expr } + BindResumableCodeDefinitions envR bodyExpr + + // Eliminate 'if __useResumableCode ...' + | IfUseResumableStateMachinesExpr g (thenExpr, _) -> + if sm_verbose then printfn "eliminating 'if __useResumableCode...'" + BindResumableCodeDefinitions env thenExpr + + | _ -> + (env, expr) + + let rec TryReduceApp (env: env) expr (args: Expr list) = + if isNil args then None else + match expr with + | Expr.TyLambda _ + | Expr.Lambda _ -> + let macroTypars, macroParamsCurried, macroBody, _rty = stripTopLambda (expr, tyOfExpr g expr) + let m = macroBody.Range + if not (isNil macroTypars) then + //warning(Error(FSComp.SR.stateMachineMacroTypars(), m)) + None + else + let macroParams = List.concat macroParamsCurried + let macroVal2 = mkLambdas m macroTypars macroParams (macroBody, tyOfExpr g macroBody) + if args.Length < macroParams.Length then + //warning(Error(FSComp.SR.stateMachineMacroUnderapplied(), m)) + None + else + let nowArgs, laterArgs = List.splitAt macroParams.Length args + let expandedExpr = MakeApplicationAndBetaReduce g (macroVal2, (tyOfExpr g macroVal2), [], nowArgs, m) + if sm_verbose then printfn "reduced application f = %A nowArgs= %A --> %A" macroVal2 nowArgs expandedExpr + if isNil laterArgs then + Some expandedExpr + else + if sm_verbose then printfn "application was partial, reducing further args %A" laterArgs + TryReduceApp env expandedExpr laterArgs + + | NewDelegateExpr g (_, macroParamsCurried, macroBody, _, _) -> + let m = expr.Range + let macroParams = List.concat macroParamsCurried + let macroVal2 = mkLambdas m [] macroParams (macroBody, tyOfExpr g macroBody) + if args.Length < macroParams.Length then + //warning(Error(FSComp.SR.stateMachineMacroUnderapplied(), m)) + None + else + let nowArgs, laterArgs = List.splitAt macroParams.Length args + let expandedExpr = MakeApplicationAndBetaReduce g (macroVal2, (tyOfExpr g macroVal2), [], nowArgs, m) + if sm_verbose then printfn "reduced application f = %A nowArgs= %A --> %A" macroVal2 nowArgs expandedExpr + if isNil laterArgs then + Some expandedExpr + else + if sm_verbose then printfn "application was partial, reducing further args %A" laterArgs + TryReduceApp env expandedExpr laterArgs + + | Expr.Let (bind, bodyExpr, m, _) -> + match TryReduceApp env bodyExpr args with + | Some bodyExpr2 -> Some (mkLetBind m bind bodyExpr2) + | None -> None + + | Expr.LetRec (binds, bodyExpr, m, _) -> + match TryReduceApp env bodyExpr args with + | Some bodyExpr2 -> Some (mkLetRecBinds m binds bodyExpr2) + | None -> None + + | Expr.Sequential (x1, bodyExpr, sp, ty, m) -> + match TryReduceApp env bodyExpr args with + | Some bodyExpr2 -> Some (Expr.Sequential (x1, bodyExpr2, sp, ty, m)) + | None -> None + + // This construct arises from the 'mkDefault' in the 'Throw' case of an incomplete pattern match + | Expr.Const (Const.Zero, m, ty) -> + Some (Expr.Const (Const.Zero, m, ty)) + + | Expr.Match (spBind, exprm, dtree, targets, m, ty) -> + let mutable newTyOpt = None + let targets2 = + targets |> Array.choose (fun (TTarget(vs, targetExpr, spTarget, flags)) -> + // Incomplete exception matching expressions give rise to targets with I_throw. + // and System.Runtime.ExceptionServices.ExceptionDispatchInfo::Throw(...) + // + // Keep these in the residue. + // + // In theory the type of the expression should be adjusted but code generation doesn't record the + // type in the IL + let targetExpr2Opt = + match targetExpr, newTyOpt with + | Expr.Op (TOp.ILAsm ([ AbstractIL.IL.I_throw ], [_oldTy]), a, b, c), Some newTy -> + let targetExpr2 = Expr.Op (TOp.ILAsm ([ AbstractIL.IL.I_throw ], [newTy]), a, b, c) + Some targetExpr2 + | Expr.Sequential ((Expr.Op (TOp.ILCall ( _, _, _, _, _, _, _, ilMethodRef, _, _, _), _, _, _) as e1), Expr.Const (Const.Zero, m, _oldTy), a, b, c), Some newTy when ilMethodRef.Name = "Throw" -> + let targetExpr2 = Expr.Sequential (e1, Expr.Const (Const.Zero, m, newTy), a, b, c) + Some targetExpr2 + | _ -> + + match TryReduceApp env targetExpr args with + | Some targetExpr2 -> + newTyOpt <- Some (tyOfExpr g targetExpr2) + Some targetExpr2 + | None -> + None + match targetExpr2Opt with + | Some targetExpr2 -> Some (TTarget(vs, targetExpr2, spTarget, flags)) + | None -> None) + if targets2.Length = targets.Length then + Some (Expr.Match (spBind, exprm, dtree, targets2, m, ty)) + else + None + + | WhileExpr (sp1, sp2, guardExpr, bodyExpr, m) -> + match TryReduceApp env bodyExpr args with + | Some bodyExpr2 -> Some (mkWhile g (sp1, sp2, guardExpr, bodyExpr2, m)) + | None -> None + + | TryFinallyExpr (sp1, sp2, ty, bodyExpr, compensation, m) -> + match TryReduceApp env bodyExpr args with + | Some bodyExpr2 -> Some (mkTryFinally g (bodyExpr2, compensation, m, ty, sp1, sp2)) + | None -> None + + | TryWithExpr (spTry, spWith, resTy, bodyExpr, filterVar, filterExpr, handlerVar, handlerExpr, m) -> + match TryReduceApp env bodyExpr args with + | Some bodyExpr2 -> Some (mkTryWith g (bodyExpr2, filterVar, filterExpr, handlerVar, handlerExpr, m, resTy, spTry, spWith)) + | None -> None + + | _ -> + None + + // Apply a single expansion of resumable code at the outermost position in an arbitrary expression + let rec TryReduceExpr (env: env) expr args remake = + if sm_verbose then printfn "expanding defns and reducing %A..." expr + //if sm_verbose then printfn "checking %A for possible resumable code application..." expr + match expr with + // defn --> [expand_code] + | Expr.Val (defnRef, _, _) when env.ResumableCodeDefns.ContainsVal defnRef.Deref -> + let defn = env.ResumableCodeDefns.[defnRef.Deref] + if sm_verbose then printfn "found resumable code %A --> %A" defnRef defn + // Expand the resumable code definition + match TryReduceApp env defn args with + | Some expandedExpr -> + if sm_verbose then printfn "expanded resumable code %A --> %A..." defnRef expandedExpr + Some expandedExpr + | None -> + Some (remake defn) + + // defn.Invoke x --> let arg = x in [defn][arg/x] + | ResumableCodeInvoke g (_, f, args2, _, rebuild) -> + if sm_verbose then printfn "found delegate invoke in possible reduction, f = %A, args now %A..." f (args2 @ args) + TryReduceExpr env f (args2 @ args) (fun f2 -> remake (rebuild (f2, args2))) + + // defn x --> let arg = x in [defn][arg/x] + | Expr.App (f, _fty, _tyargs, args2, _m) -> + if sm_verbose then printfn "found function invoke in possible reduction, f = %A, args now %A..." f (args2 @ args) + TryReduceExpr env f (args2 @ args) (fun f2 -> remake (Expr.App (f2, _fty, _tyargs, args2, _m))) + + | _ -> + //let (env, expr) = BindResumableCodeDefinitions env expr + match TryReduceApp env expr args with + | Some expandedExpr -> + if sm_verbose then printfn "reduction = %A, args = %A --> %A..." expr args expandedExpr + Some expandedExpr + | None -> + None + + // Repeated top-down rewrite + let makeRewriteEnv (env: env) = + { PreIntercept = Some (fun cont e -> match TryReduceExpr env e [] id with Some e2 -> Some (cont e2) | None -> None) + PostTransform = (fun _ -> None) + PreInterceptBinding = None + IsUnderQuotations=true } + + let ConvertStateMachineLeafExpression (env: env) expr = + if sm_verbose then printfn "ConvertStateMachineLeafExpression for %A..." expr + expr |> RewriteExpr (makeRewriteEnv env) + + let ConvertStateMachineLeafDecisionTree (env: env) expr = + if sm_verbose then printfn "ConvertStateMachineLeafDecisionTree for %A..." expr + expr |> RewriteDecisionTree (makeRewriteEnv env) + + /// Repeatedly find outermost expansion definitions and apply outermost expansions + let rec RepeatBindAndApplyOuterDefinitions (env: env) expr = + if sm_verbose then printfn "RepeatBindAndApplyOuterDefinitions for %A..." expr + let env2, expr2 = BindResumableCodeDefinitions env expr + match TryReduceExpr env2 expr2 [] id with + | Some res -> RepeatBindAndApplyOuterDefinitions env2 res + | None -> env2, expr2 + + // Detect a state machine with a single method override + let (|ExpandedStateMachineInContext|_|) inputExpr = + // All expanded resumable code state machines e.g. 'task { .. }' begin with a bind of @builder or 'defn' + let env, expr = BindResumableCodeDefinitions env.Empty inputExpr + match expr with + | StructStateMachineExpr g + (dataTy, + (moveNextThisVar, moveNextBody), + (setStateMachineThisVar, setStateMachineStateVar, setStateMachineBody), + (afterCodeThisVar, afterCodeBody)) -> + let templateStructTy = g.mk_ResumableStateMachine_ty dataTy + let env = { env with TemplateStructTy = Some templateStructTy } + if sm_verbose then printfn "Found struct machine..." + if sm_verbose then printfn "Found struct machine jump table call..." + let setStateMachineBodyR = ConvertStateMachineLeafExpression env setStateMachineBody + let afterCodeBodyR = ConvertStateMachineLeafExpression env afterCodeBody + let remake2 (moveNextExprR, stateVars, thisVars) = + if sm_verbose then + printfn "----------- AFTER REWRITE moveNextExprWithJumpTable ----------------------" + printfn "%s" (DebugPrint.showExpr g moveNextExprR) + printfn "----------- AFTER REWRITE setStateMachineBodyR ----------------------" + printfn "%s" (DebugPrint.showExpr g setStateMachineBodyR) + printfn "----------- AFTER REWRITE afterCodeBodyR ----------------------" + printfn "%s" (DebugPrint.showExpr g afterCodeBodyR) + LoweredStateMachine + (templateStructTy, dataTy, stateVars, thisVars, + (moveNextThisVar, moveNextExprR), + (setStateMachineThisVar, setStateMachineStateVar, setStateMachineBodyR), + (afterCodeThisVar, afterCodeBodyR)) + Some (env, remake2, moveNextBody) + | _ -> + None + + // A utility to add a jump table an expression + let addPcJumpTable m (pcs: int list) (pc2lab: Map) pcExpr expr = + if pcs.IsEmpty then + expr + else + let initLabel = IL.generateCodeLabel() + let mbuilder = new MatchBuilder(DebugPointAtBinding.NoneAtInvisible, m ) + let mkGotoLabelTarget lab = mbuilder.AddResultTarget(Expr.Op (TOp.Goto lab, [], [], m), DebugPointForTarget.No) + let dtree = + TDSwitch(pcExpr, + [ // Yield one target for each PC, where the action of the target is to goto the appropriate label + for pc in pcs do + yield mkCase(DecisionTreeTest.Const(Const.Int32 pc), mkGotoLabelTarget pc2lab.[pc]) ], + // The default is to go to pcInit + Some(mkGotoLabelTarget initLabel), + m) + + let table = mbuilder.Close(dtree, m, g.int_ty) + mkCompGenSequential m table (mkLabelled m initLabel expr) + + /// Detect constructs allowed in state machines + let rec ConvertResumableCode env (pcValInfo: ((Val * Expr) * Expr) option) expr : Result = + if sm_verbose then + printfn "---------ConvertResumableCode-------------------" + printfn "%s" (DebugPrint.showExpr g expr) + printfn "---------" + + let env, expr = RepeatBindAndApplyOuterDefinitions env expr + + if sm_verbose then + printfn "After RepeatBindAndApplyOuterDefinitions:\n%s" (DebugPrint.showExpr g expr) + printfn "---------" + + // Detect the different permitted constructs in the expanded state machine + let res = + match expr with + | ResumableCodeInvoke g (_, _, _, m, _) -> + Result.Error (FSComp.SR.reprResumableCodeInvokeNotReduced(m.ToShortString())) + + // Eliminate 'if __useResumableCode ...' within. + | IfUseResumableStateMachinesExpr g (thenExpr, _) -> + ConvertResumableCode env pcValInfo thenExpr + + | ResumableEntryMatchExpr g (noneBranchExpr, someVar, someBranchExpr, _rebuild) -> + ConvertResumableEntry env pcValInfo (noneBranchExpr, someVar, someBranchExpr, _rebuild) + + | ResumeAtExpr g pcExpr -> + ConvertResumableResumeAt env (pcExpr, expr.Range) + + // The expanded code for state machines may use sequential binding and sequential execution. + // + // let __stack_step = e1 in e2 + // e1; e2 + // + // A binding 'let .. = ... in ... ' is considered part of the state machine logic + // if it uses a binding variable starting with '__stack_*'. + // If this case 'e1' becomes part of the state machine too. + | SequentialResumableCode g (e1, e2, _m, recreate) -> + ConvertResumableSequential env pcValInfo (e1, e2, _m, recreate) + + // The expanded code for state machines may use while loops... + | WhileExpr (sp1, sp2, guardExpr, bodyExpr, m) -> + ConvertResumableWhile env pcValInfo (sp1, sp2, guardExpr, bodyExpr, m) + + // The expanded code for state machines should not normally contain try/finally as any resumptions will repeatedly execute the finally. + // However we include the synchronous version of the construct here for completeness. + | TryFinallyExpr (sp1, sp2, ty, e1, e2, m) -> + ConvertResumableTryFinally env pcValInfo (sp1, sp2, ty, e1, e2, m) + + // The expanded code for state machines may use for loops, however the + // body must be synchronous. + | ForLoopExpr (sp1, sp2, e1, e2, v, e3, m) -> + ConvertResumableFastIntegerForLoop env pcValInfo (sp1, sp2, e1, e2, v, e3, m) + + // The expanded code for state machines may use try/with.... + | TryWithExpr (spTry, spWith, resTy, bodyExpr, filterVar, filterExpr, handlerVar, handlerExpr, m) -> + ConvertResumableTryWith env pcValInfo (spTry, spWith, resTy, bodyExpr, filterVar, filterExpr, handlerVar, handlerExpr, m) + + // control-flow match + | Expr.Match (spBind, exprm, dtree, targets, m, ty) -> + ConvertResumableMatch env pcValInfo (spBind, exprm, dtree, targets, m, ty) + + // Non-control-flow let binding can appear as part of state machine. The body is considered state-machine code, + // the expression being bound is not. + | Expr.Let (bind, bodyExpr, m, _) + // Restriction: compilation of sequence expressions containing non-toplevel constrained generic functions is not supported + when bind.Var.IsCompiledAsTopLevel || not (IsGenericValWithGenericConstraints g bind.Var) -> + ConvertResumableLet env pcValInfo (bind, bodyExpr, m) + + | Expr.LetRec _ -> + Result.Error (FSComp.SR.reprResumableCodeContainsLetRec()) + + // Arbitrary expression + | _ -> + let exprR = ConvertStateMachineLeafExpression env expr + { phase1 = exprR + phase2 = (fun _ctxt -> exprR) + entryPoints = [] + stateVars = [] + thisVars = [] + resumableVars = emptyFreeVars } + |> Result.Ok + + if sm_verbose then + match res with + | Result.Ok res -> + printfn "-------------------" + printfn "Phase 1 Done for %s" (DebugPrint.showExpr g res.phase1) + printfn "Phase 1 Done, resumableVars = %A" (res.resumableVars.FreeLocals |> Zset.elements |> List.map (fun v -> v.CompiledName(g.CompilerGlobalState)) |> String.concat ",") + printfn "Phase 1 Done, stateVars = %A" (res.stateVars |> List.map (fun v -> v.CompiledName(g.CompilerGlobalState)) |> String.concat ",") + printfn "Phase 1 Done, thisVars = %A" (res.thisVars |> List.map (fun v -> v.CompiledName(g.CompilerGlobalState)) |> String.concat ",") + printfn "-------------------" + | Result.Error msg-> + printfn "Phase 1 failed: %s" msg + printfn "Phase 1 failed for %s" (DebugPrint.showExpr g expr) + res + + and ConvertResumableEntry env pcValInfo (noneBranchExpr, someVar, someBranchExpr, _rebuild) = + if sm_verbose then printfn "ResumableEntryMatchExpr" + // printfn "found sequential" + let reenterPC = genPC() + let envSome = { env with ResumableCodeDefns = env.ResumableCodeDefns.Add someVar (mkInt g someVar.Range reenterPC) } + let resNone = ConvertResumableCode env pcValInfo noneBranchExpr + let resSome = ConvertResumableCode envSome pcValInfo someBranchExpr + + match resNone, resSome with + | Result.Ok resNone, Result.Ok resSome -> + let resumableVars = unionFreeVars (freeInExpr CollectLocals resNone.phase1) resSome.resumableVars + let m = someBranchExpr.Range + let recreate reenterLabOpt e1 e2 = + let lab = (match reenterLabOpt with Some l -> l | _ -> IL.generateCodeLabel()) + mkCond DebugPointAtBinding.NoneAtSticky DebugPointForTarget.No m (tyOfExpr g noneBranchExpr) (mkFalse g m) (mkLabelled m lab e1) e2 + { phase1 = recreate None resNone.phase1 resSome.phase1 + phase2 = (fun ctxt -> + let generate2 = resSome.phase2 ctxt + let generate1 = resNone.phase2 ctxt + let generate = recreate (Some ctxt.[reenterPC]) generate1 generate2 + generate) + entryPoints= resSome.entryPoints @ [reenterPC] @ resNone.entryPoints + stateVars = resSome.stateVars @ resNone.stateVars + thisVars = resSome.thisVars @ resNone.thisVars + resumableVars = resumableVars } + |> Result.Ok + | Result.Error err, _ | _, Result.Error err -> Result.Error err + + and ConvertResumableResumeAt env (pcExpr , m)= + if sm_verbose then printfn "ResumeAtExpr" + // Macro-evaluate the pcExpr + let pcExprVal = ConvertStateMachineLeafExpression env pcExpr + match pcExprVal with + | Int32Expr contIdPC -> + let recreate contLabOpt = + Expr.Op (TOp.Goto (match contLabOpt with Some l -> l | _ -> IL.generateCodeLabel()), [], [], m) + + { phase1 = recreate None + phase2 = (fun ctxt -> + let generate = recreate (Some ctxt.[contIdPC]) + generate) + entryPoints = [] + stateVars = [] + thisVars = [] + resumableVars = emptyFreeVars } + |> Result.Ok + | _ -> + Result.Error(FSComp.SR.reprResumableCodeContainsDynamicResumeAtInBody()) + + and ConvertResumableSequential env pcValInfo (e1, e2, _m, recreate) = + if sm_verbose then printfn "SequentialResumableCode" + // printfn "found sequential" + let res1 = ConvertResumableCode env pcValInfo e1 + let res2 = ConvertResumableCode env pcValInfo e2 + match res1, res2 with + | Result.Ok res1, Result.Ok res2 -> + let resumableVars = + if res1.entryPoints.IsEmpty then + // res1 is synchronous + res2.resumableVars + else + // res1 is not synchronous. All of 'e2' is needed after resuming at any of the labels + unionFreeVars res1.resumableVars (freeInExpr CollectLocals res2.phase1) + + { phase1 = recreate res1.phase1 res2.phase1 + phase2 = (fun ctxt -> + let generate1 = res1.phase2 ctxt + let generate2 = res2.phase2 ctxt + let generate = recreate generate1 generate2 + generate) + entryPoints= res1.entryPoints @ res2.entryPoints + stateVars = res1.stateVars @ res2.stateVars + thisVars = res1.thisVars @ res2.thisVars + resumableVars = resumableVars } + |> Result.Ok + | Result.Error err, _ | _, Result.Error err -> Result.Error err + + and ConvertResumableWhile env pcValInfo (sp1, sp2, guardExpr, bodyExpr, m) = + if sm_verbose then printfn "WhileExpr" + + let resg = ConvertResumableCode env pcValInfo guardExpr + let resb = ConvertResumableCode env pcValInfo bodyExpr + match resg, resb with + | Result.Ok resg, Result.Ok resb -> + let eps = resg.entryPoints @ resb.entryPoints + // All free variables get captured if there are any entrypoints at all + let resumableVars = if eps.IsEmpty then emptyFreeVars else unionFreeVars (freeInExpr CollectLocals resg.phase1) (freeInExpr CollectLocals resb.phase1) + { phase1 = mkWhile g (sp1, sp2, resg.phase1, resb.phase1, m) + phase2 = (fun ctxt -> + let egR = resg.phase2 ctxt + let ebR = resb.phase2 ctxt + + // Clear the pcVal on backward branch, causing jump tables at entry to nested try-blocks to not activate + let ebR2 = + match pcValInfo with + | None -> ebR + | Some ((pcVal, _), _) -> + mkCompGenThenDoSequential m + ebR + (mkValSet m (mkLocalValRef pcVal) (mkZero g m)) + + mkWhile g (sp1, sp2, egR, ebR2, m)) + entryPoints= eps + stateVars = resg.stateVars @ resb.stateVars + thisVars = resg.thisVars @ resb.thisVars + resumableVars = resumableVars } + |> Result.Ok + | Result.Error err, _ | _, Result.Error err -> Result.Error err + + and ConvertResumableTryFinally env pcValInfo (sp1, sp2, ty, e1, e2, m) = + if sm_verbose then printfn "TryFinallyExpr" + let res1 = ConvertResumableCode env pcValInfo e1 + let res2 = ConvertResumableCode env pcValInfo e2 + match res1, res2 with + | Result.Ok res1, Result.Ok res2 -> + let eps = res1.entryPoints @ res2.entryPoints + if eps.Length > 0 then + Result.Error (FSComp.SR.reprResumableCodeContainsResumptionInTryFinally()) + else + { phase1 = mkTryFinally g (res1.phase1, res2.phase1, m, ty, sp1, sp2) + phase2 = (fun ctxt -> + let egR = res1.phase2 ctxt + let ebR = res2.phase2 ctxt + mkTryFinally g (egR, ebR, m, ty, sp1, sp2)) + entryPoints= eps + stateVars = res1.stateVars @ res2.stateVars + thisVars = res1.thisVars @ res2.thisVars + resumableVars = emptyFreeVars (* eps is empty, hence synchronous, no capture *) } + |> Result.Ok + | Result.Error err, _ | _, Result.Error err -> Result.Error err + + and ConvertResumableFastIntegerForLoop env pcValInfo (sp1, sp2, e1, e2, v, e3, m) = + if sm_verbose then printfn "ForLoopExpr" + let res1 = ConvertResumableCode env pcValInfo e1 + let res2 = ConvertResumableCode env pcValInfo e2 + let res3 = ConvertResumableCode env pcValInfo e3 + match res1, res2, res3 with + | Result.Ok res1, Result.Ok res2, Result.Ok res3 -> + let eps = res1.entryPoints @ res2.entryPoints @ res3.entryPoints + if eps.Length > 0 then + Result.Error(FSComp.SR.reprResumableCodeContainsFastIntegerForLoop()) + else + { phase1 = mkFor g (sp1, v, res1.phase1, sp2, res2.phase1, res3.phase1, m) + phase2 = (fun ctxt -> + let e1R = res1.phase2 ctxt + let e2R = res2.phase2 ctxt + let e3R = res3.phase2 ctxt + + // Clear the pcVal on backward branch, causing jump tables at entry to nested try-blocks to not activate + let e3R2 = + match pcValInfo with + | None -> e3R + | Some ((pcVal, _), _) -> + mkCompGenThenDoSequential m + e3R + (mkValSet m (mkLocalValRef pcVal) (mkZero g m)) + + mkFor g (sp1, v, e1R, sp2, e2R, e3R2, m)) + entryPoints= eps + stateVars = res1.stateVars @ res2.stateVars @ res3.stateVars + thisVars = res1.thisVars @ res2.thisVars @ res3.thisVars + resumableVars = emptyFreeVars (* eps is empty, hence synchronous, no capture *) } + |> Result.Ok + | Result.Error err, _, _ | _, Result.Error err, _ | _, _, Result.Error err -> Result.Error err + + and ConvertResumableTryWith env pcValInfo (spTry, spWith, resTy, bodyExpr, filterVar, filterExpr, handlerVar, handlerExpr, m) = + if sm_verbose then printfn "TryWithExpr" + let resBody = ConvertResumableCode env pcValInfo bodyExpr + let resFilter = ConvertResumableCode env pcValInfo filterExpr + let resHandler = ConvertResumableCode env pcValInfo handlerExpr + match resBody, resFilter, resHandler with + | Result.Ok resBody, Result.Ok resFilter, Result.Ok resHandler -> + let epsNope = resFilter.entryPoints @ resHandler.entryPoints + if epsNope.Length > 0 then + Result.Error(FSComp.SR.reprResumableCodeContainsResumptionInHandlerOrFilter()) + else + { phase1 = mkTryWith g (resBody.phase1, filterVar, resFilter.phase1, handlerVar, resHandler.phase1, m, resTy, spTry, spWith) + phase2 = (fun ctxt -> + // We can't jump into a try/catch block. So we jump to the start of the try/catch and add a new jump table + let pcsAndLabs = ctxt |> Map.toList + let innerPcs = resBody.entryPoints + if innerPcs.IsEmpty then + let vBodyR = resBody.phase2 ctxt + let filterExprR = resFilter.phase2 ctxt + let handlerExprR = resHandler.phase2 ctxt + mkTryWith g (vBodyR, filterVar, filterExprR, handlerVar, handlerExprR, m, resTy, spTry, spWith) + else + let innerPcSet = innerPcs |> Set.ofList + let outerLabsForInnerPcs = pcsAndLabs |> List.filter (fun (pc, _outerLab) -> innerPcSet.Contains pc) |> List.map snd + // generate the inner labels + let pcsAndInnerLabs = pcsAndLabs |> List.map (fun (pc, l) -> (pc, if innerPcSet.Contains pc then IL.generateCodeLabel() else l)) + let innerPc2Lab = Map.ofList pcsAndInnerLabs + + let vBodyR = resBody.phase2 innerPc2Lab + let filterExprR = resFilter.phase2 ctxt + let handlerExprR = resHandler.phase2 ctxt + + // Add a jump table at the entry to the try + let vBodyRWithJumpTable = + match pcValInfo with + | None -> vBodyR + | Some ((_, pcValExpr), _) -> addPcJumpTable m innerPcs innerPc2Lab pcValExpr vBodyR + let coreExpr = mkTryWith g (vBodyRWithJumpTable, filterVar, filterExprR, handlerVar, handlerExprR, m, resTy, spTry, spWith) + // Place all the outer labels just before the try + let labelledExpr = (coreExpr, outerLabsForInnerPcs) ||> List.fold (fun e l -> mkLabelled m l e) + + labelledExpr) + entryPoints= resBody.entryPoints @ resFilter.entryPoints @ resHandler.entryPoints + stateVars = resBody.stateVars @ resFilter.stateVars @ resHandler.stateVars + thisVars = resBody.thisVars @ resFilter.thisVars @ resHandler.thisVars + resumableVars = unionFreeVars resBody.resumableVars (unionFreeVars(freeInExpr CollectLocals resFilter.phase1) (freeInExpr CollectLocals resHandler.phase1)) } + |> Result.Ok + | Result.Error err, _, _ | _, Result.Error err, _ | _, _, Result.Error err -> Result.Error err + + and ConvertResumableMatch env pcValInfo (spBind, exprm, dtree, targets, m, ty) = + if sm_verbose then printfn "MatchExpr" + // lower all the targets. + let dtreeR = ConvertStateMachineLeafDecisionTree env dtree + let tglArray = + targets |> Array.map (fun (TTarget(_vs, targetExpr, _spTarget, _)) -> + ConvertResumableCode env pcValInfo targetExpr) + match (tglArray |> Array.forall (function Result.Ok _ -> true | Result.Error _ -> false)) with + | true -> + let tglArray = tglArray |> Array.map (function Result.Ok v -> v | _ -> failwith "unreachable") + let tgl = tglArray |> Array.toList + let entryPoints = tgl |> List.collect (fun res -> res.entryPoints) + let resumableVars = + (emptyFreeVars, Array.zip targets tglArray) + ||> Array.fold (fun fvs ((TTarget(_vs, _, _spTarget, _)), res) -> + if res.entryPoints.IsEmpty then fvs else unionFreeVars fvs res.resumableVars) + let stateVars = + (targets, tglArray) ||> Array.zip |> Array.toList |> List.collect (fun (TTarget(vs, _, _, _), res) -> + let stateVars = vs |> List.filter (fun v -> res.resumableVars.FreeLocals.Contains(v)) |> List.map mkLocalValRef + stateVars @ res.stateVars) + let thisVars = tglArray |> Array.toList |> List.collect (fun res -> res.thisVars) + { phase1 = + let gtgs = + (targets, tglArray) ||> Array.map2 (fun (TTarget(vs, _, spTarget, _)) res -> + let flags = vs |> List.map (fun v -> res.resumableVars.FreeLocals.Contains(v)) + TTarget(vs, res.phase1, spTarget, Some flags)) + primMkMatch (spBind, exprm, dtreeR, gtgs, m, ty) + + phase2 = (fun ctxt -> + let gtgs = + (targets, tglArray) ||> Array.map2 (fun (TTarget(vs, _, spTarget, _)) res -> + let flags = vs |> List.map (fun v -> res.resumableVars.FreeLocals.Contains(v)) + TTarget(vs, res.phase2 ctxt, spTarget, Some flags)) + let generate = primMkMatch (spBind, exprm, dtreeR, gtgs, m, ty) + generate) + + entryPoints = entryPoints + stateVars = stateVars + resumableVars = resumableVars + thisVars = thisVars } + |> Result.Ok + | _ -> tglArray |> Array.find (function Result.Ok _ -> false | Result.Error _ -> true) + + and ConvertResumableLet env pcValInfo (bind, bodyExpr, m) = + // Non-control-flow let binding can appear as part of state machine. The body is considered state-machine code, + // the expression being bound is not. + if sm_verbose then printfn "LetExpr (non-control-flow, rewrite rhs)" + + // Rewrite the expression on the r.h.s. of the binding + let bindExpr = ConvertStateMachineLeafExpression env bind.Expr + let bind = mkBind bind.DebugPoint bind.Var bindExpr + if sm_verbose then printfn "LetExpr (non-control-flow, body)" + + let resBody = ConvertResumableCode env pcValInfo bodyExpr + + match resBody with + | Result.Ok resBody -> + // The isByrefTy check is an adhoc check to avoid capturing the 'this' parameter of a struct state machine + // You might think we could do this: + // + // let sm = &this + // ... await point ... + // ... sm .... + // However the 'sm' won't be set on that path. + if isByrefTy g bind.Var.Type && + (match env.TemplateStructTy with + | None -> false + | Some ty -> typeEquiv g ty (destByrefTy g bind.Var.Type)) then + RepresentBindingAsThis bind resBody m + |> Result.Ok + elif bind.Var.IsCompiledAsTopLevel || + not (resBody.resumableVars.FreeLocals.Contains(bind.Var)) || + bind.Var.LogicalName.StartsWith stackVarPrefix then + if sm_verbose then printfn "LetExpr (non-control-flow, rewrite rhs, RepresentBindingAsTopLevelOrLocal)" + RepresentBindingAsTopLevelOrLocal bind resBody m + |> Result.Ok + else + if sm_verbose then printfn "LetExpr (non-control-flow, rewrite rhs, RepresentBindingAsStateVar)" + // printfn "found state variable %s" bind.Var.DisplayName + RepresentBindingAsStateVar g bind resBody m + |> Result.Ok + | Result.Error msg -> + Result.Error msg + + member _.Apply(overallExpr, altExprOpt) = + + let fallback msg = + match altExprOpt with + | None -> + LoweredStateMachineResult.NoAlternative msg + | Some altExpr -> + LoweredStateMachineResult.UseAlternative (msg, altExpr) + + match overallExpr with + | ExpandedStateMachineInContext (env, remake, moveNextExpr) -> + let m = moveNextExpr.Range + match moveNextExpr with + | OptionalResumeAtExpr g (pcExprOpt, codeExpr) -> + let env, codeExprR = RepeatBindAndApplyOuterDefinitions env codeExpr + let frees = (freeInExpr CollectLocals overallExpr).FreeLocals + + if frees |> Zset.exists (isExpandVar g) then + let nonfree = frees |> Zset.elements |> List.filter (isExpandVar g) |> List.map (fun v -> v.DisplayName) |> String.concat "," + let msg = FSComp.SR.reprResumableCodeValueHasNoDefinition(nonfree) + fallback msg + else + let pcExprROpt = pcExprOpt |> Option.map (ConvertStateMachineLeafExpression env) + let pcValInfo = + match pcExprROpt with + | None -> None + | Some e -> Some (mkMutableCompGenLocal e.Range "pcVal" g.int32_ty, e) + + if sm_verbose then + printfn "Found state machine override method and code expression..." + printfn "----------- OVERALL EXPRESSION FOR STATE MACHINE CONVERSION ----------------------" + printfn "%s" (DebugPrint.showExpr g overallExpr) + printfn "----------- INPUT TO STATE MACHINE CONVERSION ----------------------" + printfn "%s" (DebugPrint.showExpr g codeExpr) + printfn "----------- START STATE MACHINE CONVERSION ----------------------" + + // Perform phase1 of the conversion + let phase1 = ConvertResumableCode env pcValInfo codeExprR + match phase1 with + | Result.Error msg -> + fallback msg + | Result.Ok phase1 -> + + // Work out the initial mapping of pcs to labels + let pcs = [ 1 .. pcCount ] + let labs = pcs |> List.map (fun _ -> IL.generateCodeLabel()) + let pc2lab = Map.ofList (List.zip pcs labs) + + // Execute phase2, building the core of the method + if sm_verbose then printfn "----------- PHASE2 ----------------------" + + // Perform phase2 to build the final expression + let moveNextExprR = phase1.phase2 pc2lab + + if sm_verbose then printfn "----------- ADDING JUMP TABLE ----------------------" + + // Add the jump table + let moveNextExprWithJumpTable = + match pcValInfo with + | None -> moveNextExprR + | Some ((v,pcValExprR),pcExprR) -> mkCompGenLet m v pcExprR (addPcJumpTable m pcs pc2lab pcValExprR moveNextExprR) + + if sm_verbose then printfn "----------- REMAKE ----------------------" + + // Build the result + let res = remake (moveNextExprWithJumpTable, phase1.stateVars, phase1.thisVars) + LoweredStateMachineResult.Lowered res + + | _ -> + let msg = FSComp.SR.reprStateMachineInvalidForm() + fallback msg + +let LowerStateMachineExpr g (overallExpr: Expr) : LoweredStateMachineResult = + // Detect a state machine and convert it + let stateMachine = IsStateMachineExpr g overallExpr + + match stateMachine with + | None -> LoweredStateMachineResult.NotAStateMachine + | Some altExprOpt -> + + LowerStateMachine(g).Apply(overallExpr, altExprOpt) diff --git a/src/fsharp/LowerStateMachines.fsi b/src/fsharp/LowerStateMachines.fsi new file mode 100644 index 00000000000..5a37c4ada6f --- /dev/null +++ b/src/fsharp/LowerStateMachines.fsi @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module internal FSharp.Compiler.LowerStateMachines + +open FSharp.Compiler.TypedTree +open FSharp.Compiler.TcGlobals + +type LoweredStateMachine = + LoweredStateMachine of + templateStructTy: TType * + dataTy: TType * + stateVars: ValRef list * + thisVars: ValRef list * + moveNext: (Val * Expr) * + setStateMachine: (Val * Val * Expr) * + afterCode: (Val * Expr) + +type LoweredStateMachineResult = + /// A state machine was recognised and was compilable + | Lowered of LoweredStateMachine + + /// A state machine was recognised and was not compilable and an alternative is available + | UseAlternative of message: string * alternativeExpr: Expr + + /// A state machine was recognised and was not compilable and no alternative is available + | NoAlternative of message: string + + /// The construct was not a state machine + | NotAStateMachine + +/// Analyze a TAST expression to detect the elaborated form of a state machine expression, a special kind +/// of object expression that uses special code generation constructs. +val LowerStateMachineExpr: + g: TcGlobals -> + overallExpr: Expr -> + LoweredStateMachineResult + diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index c981e3c47df..35935167200 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -16,6 +16,8 @@ open FSharp.Compiler.AttributeChecking open FSharp.Compiler.CompilerGlobalState open FSharp.Compiler.ErrorLogger open FSharp.Compiler.Infos +open FSharp.Compiler.Text.Range +open FSharp.Compiler.Syntax.PrettyNaming open FSharp.Compiler.Syntax open FSharp.Compiler.SyntaxTreeOps open FSharp.Compiler.TcGlobals @@ -1252,12 +1254,6 @@ let AbstractAndRemapModulInfo msg g m (repackage, hidden) info = // Misc helpers //------------------------------------------------------------------------- -/// Mark some variables (the ones we introduce via abstractBigTargets) as don't-eliminate -let [] suffixForVariablesThatMayNotBeEliminated = "$cont" - -/// Indicates a ValRef generated to facilitate tuple eliminations -let [] suffixForTupleElementAssignmentTarget = "$tupleElem" - /// Type applications of F# "type functions" may cause side effects, e.g. /// let x<'a> = printfn "hello"; typeof<'a> /// In this case do not treat them as constants. @@ -1324,10 +1320,15 @@ let IsDiscardableEffectExpr expr = /// Checks is a value binding is non-discardable let ValueIsUsedOrHasEffect cenv fvs (b: Binding, binfo) = let v = b.Var - not (cenv.settings.EliminateUnusedBindings()) || + // No discarding for debug code, except InlineIfLambda + (not (cenv.settings.EliminateUnusedBindings()) && not v.InlineIfLambda) || + // No discarding for members Option.isSome v.MemberInfo || + // No discarding for bindings that have an effect (binfo.HasEffect && not (IsDiscardableEffectExpr b.Expr)) || + // No discarding for 'fixed' v.IsFixed || + // No discarding for things that are used Zset.contains v (fvs()) let rec SplitValuesByIsUsedOrHasEffect cenv fvs x = @@ -1410,14 +1411,16 @@ let TryEliminateBinding cenv _env (TBind(vspec1, e1, spBind)) e2 _m = not vspec1.IsCompilerGenerated then None elif vspec1.IsFixed then None + elif vspec1.LogicalName.StartsWith stackVarPrefix || + vspec1.LogicalName.Contains suffixForVariablesThatMayNotBeEliminated then None else + // Peephole on immediate consumption of single bindings, e.g. "let x = e in x" --> "e" // REVIEW: enhance this by general elimination of bindings to // non-side-effecting expressions that are used only once. // But note the cases below cover some instances of side-effecting expressions as well.... let IsUniqueUse vspec2 args = valEq vspec1 vspec2 - && (not (vspec2.LogicalName.Contains suffixForVariablesThatMayNotBeEliminated)) // REVIEW: this looks slow. Look only for one variable instead && (let fvs = accFreeInExprs CollectLocals args emptyFreeVars not (Zset.contains vspec1 fvs.FreeLocals)) @@ -1437,20 +1440,32 @@ let TryEliminateBinding cenv _env (TBind(vspec1, e1, spBind)) e2 _m = when IsUniqueUse vspec2 [] -> Some e1 + // Immediate consumption of function in an application in a sequential, e.g. 'let part1 = e in part1 arg; rest' + // See https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1034-lambda-optimizations.md + | Expr.Sequential(Expr.App(Expr.Val (VRefLocal vspec2, _, _), f0ty, c, args, d), rest, NormalSeq, sp, m) + when IsUniqueUse vspec2 (rest :: args) -> + Some (Expr.Sequential(Expr.App(e1, f0ty, c, args, d), rest, NormalSeq, sp, m)) + + // Immediate consumption of delegate via an application in a sequential, e.g. 'let part1 = e in part1.Invoke(args); rest' + // See https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1034-lambda-optimizations.md + | Expr.Sequential(DelegateInvokeExpr cenv.g (invokeRef, f0ty, tyargs, Expr.Val (VRefLocal vspec2, _, _), args, _), rest, NormalSeq, sp, m) + when IsUniqueUse vspec2 (rest :: args) -> + let invoke = MakeFSharpDelegateInvokeAndTryBetaReduce cenv.g (invokeRef, e1, f0ty, tyargs, args, m) + Some (Expr.Sequential(invoke, rest, NormalSeq, sp, m)) + // Immediate consumption of value by a pattern match 'let x = e in match x with ...' | Expr.Match (spMatch, _exprm, TDSwitch(Expr.Val (VRefLocal vspec2, _, _), cases, dflt, _), targets, m, ty2) - when (valEq vspec1 vspec2 && + when (valEq vspec1 vspec2 && let fvs = accFreeInTargets CollectLocals targets (accFreeInSwitchCases CollectLocals cases dflt emptyFreeVars) not (Zset.contains vspec1 fvs.FreeLocals)) -> let spMatch = spBind.Combine spMatch Some (Expr.Match (spMatch, e1.Range, TDSwitch(e1, cases, dflt, m), targets, m, ty2)) - // Immediate consumption of value as a function 'let f = e in f ...' and 'let x = e in f ... x ...' + // Immediate use of value as part of an application. 'let f = e in f ...' and 'let x = e in f ... x ...' // Note functions are evaluated before args // Note: do not include functions with a single arg of unit type, introduced by abstractBigTargets - | Expr.App (f, f0ty, tyargs, args, m) - when not (vspec1.LogicalName.Contains suffixForVariablesThatMayNotBeEliminated) -> + | Expr.App (f, f0ty, tyargs, args, m) -> match GetImmediateUseContext [] (f :: args) with | Some([], rargs) -> Some (MakeApplicationAndBetaReduce cenv.g (e1, f0ty, [tyargs], rargs, m)) | Some(f :: largs, rargs) -> Some (MakeApplicationAndBetaReduce cenv.g (f, f0ty, [tyargs], largs @ (e1 :: rargs), m)) @@ -1502,7 +1517,7 @@ let (|TDBoolSwitch|_|) dtree = /// Check target that have a constant bool value let (|ConstantBoolTarget|_|) target = match target with - | TTarget([], Expr.Const (Const.Bool b,_,_),_) -> Some b + | TTarget([], Expr.Const (Const.Bool b, _, _), _, _) -> Some b | _ -> None /// Is this a tree, where each decision is a two-way switch (to prevent later duplication of trees), and each branch returns or true/false, @@ -1516,7 +1531,7 @@ let rec CountBoolLogicTree ((targets: DecisionTreeTarget[], costOuterCaseTree, c | TDSuccess([], idx) -> match targets.[idx] with | ConstantBoolTarget result -> (if result = testBool then costOuterCaseTree else costOuterDefaultTree), 0 - | TTarget([], _exp, _) -> costOuterCaseTree + costOuterDefaultTree, 10 + | TTarget([], _exp, _, _) -> costOuterCaseTree + costOuterDefaultTree, 10 | _ -> 100, 100 | _ -> 100, 100 @@ -1532,7 +1547,7 @@ let rec RewriteBoolLogicTree ((targets: DecisionTreeTarget[], outerCaseTree, out | TDSuccess([], idx) -> match targets.[idx] with | ConstantBoolTarget result -> if result = testBool then outerCaseTree else outerDefaultTree - | TTarget([], exp, _) -> mkBoolSwitch exp.Range exp (if testBool then outerCaseTree else outerDefaultTree) (if testBool then outerDefaultTree else outerCaseTree) + | TTarget([], exp, _, _) -> mkBoolSwitch exp.Range exp (if testBool then outerCaseTree else outerDefaultTree) (if testBool then outerDefaultTree else outerCaseTree) | _ -> failwith "CountBoolLogicTree should exclude this case" | _ -> failwith "CountBoolLogicTree should exclude this case" @@ -1671,9 +1686,9 @@ let TryRewriteBranchingTupleBinding g (v: Val) rhs tgtSeqPtOpt body m = match expr with | Expr.Match (sp, inputRange, decision, targets, fullRange, ty) -> // Recurse down every if/match branch - let rewrittenTargets = targets |> Array.choose (fun (TTarget (vals, targetExpr, sp)) -> + let rewrittenTargets = targets |> Array.choose (fun (TTarget (vals, targetExpr, sp, flags)) -> match dive g m requisites targetExpr with - | Some rewritten -> TTarget (vals, rewritten, sp) |> Some + | Some rewritten -> TTarget (vals, rewritten, sp, flags) |> Some | _ -> None) // If not all branches can be rewritten, keep the original expression as it is @@ -1685,7 +1700,7 @@ let TryRewriteBranchingTupleBinding g (v: Val) rhs tgtSeqPtOpt body m = // Replace tuple allocation with mutations of locals let _, _, _, vrefs = requisites.Value List.map2 (mkValSet m) vrefs tupleElements - |> mkSequentials DebugPointAtSequential.StmtOnly g m + |> mkSequentials DebugPointAtSequential.SuppressStmt g m |> Some | Expr.Sequential (e1, e2, kind, sp, m) -> match dive g m requisites e2 with @@ -1849,10 +1864,10 @@ let rec tryRewriteToSeqCombinators g (e: Expr) = // match --> match | Expr.Match (spBind, exprm, pt, targets, m, _ty) -> - let targets = targets |> Array.map (fun (TTarget(vs, e, spTarget)) -> match tryRewriteToSeqCombinators g e with None -> None | Some e -> Some(TTarget(vs, e, spTarget))) + let targets = targets |> Array.map (fun (TTarget(vs, e, spTarget, flags)) -> match tryRewriteToSeqCombinators g e with None -> None | Some e -> Some(TTarget(vs, e, spTarget, flags))) if targets |> Array.forall Option.isSome then let targets = targets |> Array.map Option.get - let ty = targets |> Array.pick (fun (TTarget(_, e, _)) -> Some(tyOfExpr g e)) + let ty = targets |> Array.pick (fun (TTarget(_, e, _, _)) -> Some(tyOfExpr g e)) Some (Expr.Match (spBind, exprm, pt, targets, m, ty)) else None @@ -1992,12 +2007,21 @@ let rec OptimizeExpr cenv (env: IncrementalOptimizationEnv) expr = Info=UnknownValue } | Expr.Obj (_, ty, basev, createExpr, overrides, iimpls, m) -> - OptimizeObjectExpr cenv env (ty, basev, createExpr, overrides, iimpls, m) + match expr with + | NewDelegateExpr cenv.g (lambdaId, vsl, body, _, remake) -> + OptimizeNewDelegateExpr cenv env (lambdaId, vsl, body, remake) + | _ -> + OptimizeObjectExpr cenv env (ty, basev, createExpr, overrides, iimpls, m) | Expr.Op (op, tyargs, args, m) -> OptimizeExprOp cenv env (op, tyargs, args, m) | Expr.App (f, fty, tyargs, argsl, m) -> + match expr with + | DelegateInvokeExpr cenv.g (iref, fty, tyargs, delegatef, args, m) -> + OptimizeFSharpDelegateInvoke cenv env (iref, delegatef, fty, tyargs, args, m) + | _ -> + // eliminate uses of query match TryDetectQueryQuoteAndRun cenv expr with | Some newExpr -> OptimizeExpr cenv env newExpr @@ -2049,7 +2073,7 @@ and OptimizeObjectExpr cenv env (ty, baseValOpt, basecall, overrides, iimpls, m) let basecallR, basecallinfo = OptimizeExpr cenv env basecall let overridesR, overrideinfos = OptimizeMethods cenv env baseValOpt overrides let iimplsR, iimplsinfos = OptimizeInterfaceImpls cenv env baseValOpt iimpls - let exprR=mkObjExpr(ty, baseValOpt, basecallR, overridesR, iimplsR, m) + let exprR = mkObjExpr (ty, baseValOpt, basecallR, overridesR, iimplsR, m) exprR, { TotalSize=closureTotalSize + basecallinfo.TotalSize + AddTotalSizes overrideinfos + AddTotalSizes iimplsinfos FunctionSize=1 (* a newobj *) HasEffect=true @@ -2222,7 +2246,7 @@ and OptimizeExprOpReductionsAfter cenv env (op, tyargs, argsR, arginfos, m) = | _ -> None match knownValue with | Some valu -> - match TryOptimizeVal cenv env (None, false, valu, m) with + match TryOptimizeVal cenv env (None, false, false, valu, m) with | Some res -> OptimizeExpr cenv env res (* discard e1 since guard ensures it has no effects *) | None -> OptimizeExprOpFallback cenv env (op, tyargs, argsR, m) arginfos valu | None -> OptimizeExprOpFallback cenv env (op, tyargs, argsR, m) arginfos UnknownValue @@ -2425,6 +2449,24 @@ and OptimizeLinearExpr cenv env expr contf = let expr = if cenv.settings.ExpandStructuralValues() then ExpandStructuralBinding cenv expr else expr let expr = stripExpr expr + // Matching on 'match __resumableEntry() with ...` is really a first-class language construct which we + // don't optimize separately + match expr with + | ResumableEntryMatchExpr cenv.g (noneBranchExpr, someVar, someBranchExpr, rebuild) -> + let noneBranchExprR, e1info = OptimizeExpr cenv env noneBranchExpr + let env = BindInternalValToUnknown cenv someVar env + let someBranchExprR, e2info = OptimizeExpr cenv env someBranchExpr + let exprR = rebuild (noneBranchExprR, someBranchExprR) + let infoR = + { TotalSize = e1info.TotalSize + e2info.TotalSize + FunctionSize = e1info.FunctionSize + e2info.FunctionSize + HasEffect = true + MightMakeCriticalTailcall = false + Info = UnknownValue } + contf (exprR, infoR) + + | _ -> + match expr with | Expr.Sequential (e1, e2, flag, spSeq, m) -> let e1R, e1info = OptimizeExpr cenv env e1 @@ -2478,7 +2520,7 @@ and OptimizeLinearExpr cenv env expr contf = // This ConsiderSplitToMethod is performed because it is present in OptimizeDecisionTreeTarget let e2, e2info = ConsiderSplitToMethod cenv.settings.abstractBigTargets cenv.settings.bigTargetSize cenv env (e2, e2info) let tinfos = [tg1info; e2info] - let targetsR = [tg1; TTarget([], e2, spTarget2)] + let targetsR = [tg1; TTarget([], e2, spTarget2, None)] OptimizeMatchPart2 cenv (spMatch, exprm, dtreeR, targetsR, dinfo, tinfos, m, ty))) | LinearOpExpr (op, tyargs, argsHead, argLast, m) -> @@ -2503,9 +2545,9 @@ and OptimizeTryFinally cenv env (spTry, spFinally, e1, e2, m, ty) = if cenv.settings.EliminateTryWithAndTryFinally () && not e1info.HasEffect then let sp = match spTry with - | DebugPointAtTry.Yes _ -> DebugPointAtSequential.Both - | DebugPointAtTry.Body -> DebugPointAtSequential.Both - | DebugPointAtTry.No -> DebugPointAtSequential.StmtOnly + | DebugPointAtTry.Yes _ -> DebugPointAtSequential.SuppressNeither + | DebugPointAtTry.Body -> DebugPointAtSequential.SuppressNeither + | DebugPointAtTry.No -> DebugPointAtSequential.SuppressStmt Expr.Sequential (e1R, e2R, ThenDoSeq, sp, m), info else mkTryFinally cenv.g (e1R, e2R, m, ty, spTry, spFinally), @@ -2557,16 +2599,21 @@ and OptimizeTraitCall cenv env (traitInfo, args, m) = let argsR, arginfos = OptimizeExprsThenConsiderSplits cenv env args OptimizeExprOpFallback cenv env (TOp.TraitCall traitInfo, [], argsR, m) arginfos UnknownValue -and CopyExprForInlining cenv expr m = - // Debug points are erased when doing cross-assembly inlining - // Locals are marked compiler generated when doing cross-assembly inlining - expr - |> copyExpr cenv.g CloneAllAndMarkExprValsAsCompilerGenerated - |> remarkExpr m +and CopyExprForInlining cenv isInlineIfLambda expr m = + // 'InlineIfLambda' doesn't erase ranges, e.g. if the lambda is user code. + if isInlineIfLambda then + expr + |> copyExpr cenv.g CloneAll + else + // Debug points are erased when doing inlining + // Locals are marked compiler generated when doing inlining + expr + |> copyExpr cenv.g CloneAllAndMarkExprValsAsCompilerGenerated + |> remarkExpr m /// Make optimization decisions once we know the optimization information /// for a value -and TryOptimizeVal cenv env (vOpt: ValRef option, mustInline, valInfoForVal, m) = +and TryOptimizeVal cenv env (vOpt: ValRef option, mustInline, inlineIfLambda, valInfoForVal, m) = match valInfoForVal with // Inline all constants immediately @@ -2574,13 +2621,13 @@ and TryOptimizeVal cenv env (vOpt: ValRef option, mustInline, valInfoForVal, m) Some (Expr.Const (c, m, ty)) | SizeValue (_, detail) -> - TryOptimizeVal cenv env (vOpt, mustInline, detail, m) + TryOptimizeVal cenv env (vOpt, mustInline, inlineIfLambda, detail, m) | ValValue (vR, detail) -> // Inline values bound to other values immediately // Prefer to inline using the more specific info if possible // If the more specific info didn't reveal an inline then use the value - match TryOptimizeVal cenv env (vOpt, mustInline, detail, m) with + match TryOptimizeVal cenv env (vOpt, mustInline, inlineIfLambda, detail, m) with | Some e -> Some e | None -> // If we have proven 'v = compilerGeneratedValue' @@ -2598,8 +2645,8 @@ and TryOptimizeVal cenv env (vOpt: ValRef option, mustInline, valInfoForVal, m) | ConstExprValue(_size, expr) -> Some (remarkExpr m (copyExpr cenv.g CloneAllAndMarkExprValsAsCompilerGenerated expr)) - | CurriedLambdaValue (_, _, _, expr, _) when mustInline -> - let exprCopy = CopyExprForInlining cenv expr m + | CurriedLambdaValue (_, _, _, expr, _) when mustInline || inlineIfLambda -> + let exprCopy = CopyExprForInlining cenv inlineIfLambda expr m Some exprCopy | TupleValue _ | UnionCaseValue _ | RecdValue _ when mustInline -> @@ -2613,7 +2660,7 @@ and TryOptimizeVal cenv env (vOpt: ValRef option, mustInline, valInfoForVal, m) | _ -> None and TryOptimizeValInfo cenv env m vinfo = - if vinfo.HasEffect then None else TryOptimizeVal cenv env (None, false, vinfo.Info, m) + if vinfo.HasEffect then None else TryOptimizeVal cenv env (None, false, false, vinfo.Info, m) /// Add 'v1 = v2' information into the information stored about a value and AddValEqualityInfo g m (v: ValRef) info = @@ -2632,7 +2679,7 @@ and AddValEqualityInfo g m (v: ValRef) info = and OptimizeVal cenv env expr (v: ValRef, m) = let valInfoForVal = GetInfoForVal cenv env m v - match TryOptimizeVal cenv env (Some v, v.MustInline, valInfoForVal.ValExprInfo, m) with + match TryOptimizeVal cenv env (Some v, v.MustInline, v.InlineIfLambda, valInfoForVal.ValExprInfo, m) with | Some e -> // don't reoptimize inlined lambdas until they get applied to something match e with @@ -2649,7 +2696,10 @@ and OptimizeVal cenv env expr (v: ValRef, m) = e, AddValEqualityInfo cenv.g m v einfo | None -> - if v.MustInline then error(Error(FSComp.SR.optFailedToInlineValue(v.DisplayName), m)) + if v.MustInline then + error(Error(FSComp.SR.optFailedToInlineValue(v.DisplayName), m)) + if v.InlineIfLambda then + warning(Error(FSComp.SR.optFailedToInlineSuggestedValue(v.DisplayName), m)) expr, (AddValEqualityInfo cenv.g m v { Info=valInfoForVal.ValExprInfo HasEffect=false @@ -2957,7 +3007,7 @@ and TryInlineApplication cenv env finfo (tyargs: TType list, args: Expr list, m) // Inlining lambda (* ---------- printf "Inlining lambda near %a = %s\n" outputRange m (showL (exprL f2)) (* JAMES: *) ----------*) - let f2R = CopyExprForInlining cenv f2 m + let f2R = CopyExprForInlining cenv false f2 m // Optimizing arguments after inlining @@ -2972,6 +3022,88 @@ and TryInlineApplication cenv env finfo (tyargs: TType list, args: Expr list, m) | _ -> None +// Optimize the application of computed functions. +// See https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1034-lambda-optimizations.md +// +// Always lift 'let', 'letrec', sequentials and 'match' off computed functions so +// (let x = 1 in fexpr) arg ---> let x = 1 in fexpr arg +// (let rec binds in fexpr) arg ---> let rec binds in fexpr arg +// (e; fexpr) arg ---> e; fexpr arg +// (match e with pat1 -> func1 | pat2 -> func2) args --> (match e with pat1 -> func1 args | pat2 -> func2 args) +// +// This is always valid because functions are computed before arguments. +// We do this even in debug code as it doesn't change debugging properties. +// This is useful in DSLs that compute functions and weave them together with user code, e.g. +// inline F# computation expressions. +// +// The case of 'match' is particularly awkward because we are cloning 'args' on the right. We want to avoid +// this in the common case, so we first collect up all the "function holes" +// (let x = 1 in ) +// (let rec binds in ) +// (e; ) +// (match e with pat1 -> | pat2 -> ) +// then work out if we only have one of them. While collecting up the holes we build up a function to rebuild the +// overall expression given new expressions ("func" --> "func args" and its optimization). +// +// If there a multiple holes, we had a "match" somewhere, and we abandon OptimizeApplication and simply apply the +// function to the arguments at each hole (copying the arguments), then reoptimize the whole result. +// +// If there is a single hole, we proceed with OptimizeApplication +and StripPreComputationsFromComputedFunction g f0 args mkApp = + + // Identify sub-expressions that are the lambda functions to apply. + // There may be more than one because of multiple 'match' branches. + let rec strip (f: Expr) : Expr list * (Expr list -> Expr) = + match stripExpr f with + | Expr.Let (bind, bodyExpr, m, _) -> + let fs, remake = strip bodyExpr + fs, (remake >> mkLetBind m bind) + | Expr.LetRec (binds, bodyExpr, m, _) -> + let fs, remake = strip bodyExpr + fs, (remake >> mkLetRecBinds m binds) + | Expr.Sequential (x1, bodyExpr, NormalSeq, sp, m) -> + let fs, remake = strip bodyExpr + fs, (remake >> (fun bodyExpr2 -> Expr.Sequential (x1, bodyExpr2, NormalSeq, sp, m))) + + // Matches which compute a different function on each branch are awkward, see above. + | Expr.Match (spMatch, exprm, dtree, targets, dflt, _ty) when targets.Length <= 2 -> + let fsl, targetRemakes = + targets + |> Array.map (fun (TTarget(vs, bodyExpr, spTarget, flags)) -> + let fs, remake = strip bodyExpr + fs, (fun holes -> TTarget(vs, remake holes, spTarget, flags))) + |> Array.unzip + + let fs = List.concat fsl + let chunkSizes = Array.map List.length fsl + let remake (newExprs: Expr list) = + let newExprsInChunks, _ = + ((newExprs,0), chunkSizes) ||> Array.mapFold (fun (acc,i) chunkSize -> + let chunk = acc.[0..chunkSize-1] + let acc = acc.[chunkSize..] + chunk, (acc, i+chunkSize)) + let targetsR = (newExprsInChunks, targetRemakes) ||> Array.map2 (fun newExprsChunk targetRemake -> targetRemake newExprsChunk) + let tyR = tyOfExpr g targetsR.[0].TargetExpression + Expr.Match (spMatch, exprm, dtree, targetsR, dflt, tyR) + fs, remake + + | _ -> + [f], (fun newExprs -> (assert (newExprs.Length = 1)); List.head newExprs) + + match strip f0 with + | [f], remake -> + // If the computed function has only one interesting function result expression then progress as normal + Choice2Of2 (f, (fun x -> remake [x])) + | fs, remake -> + // If there is a match with multiple branches then apply each function to a copy of the arguments, + // remake the whole expression and return an indicator to reoptimize that. + let applied = + fs |> List.mapi (fun i f -> + let argsR = if i = 0 then args else List.map (copyExpr g CloneAll) args + mkApp f argsR) + let remade = remake applied + Choice1Of2 remade + /// When optimizing a function in an application, use the whole range including arguments for the range /// to apply to 'inline' code and OptimizeFuncInApplication cenv env f0 mWithArgs = @@ -2984,17 +3116,24 @@ and OptimizeFuncInApplication cenv env f0 mWithArgs = /// Optimize/analyze an application of a function to type and term arguments and OptimizeApplication cenv env (f0, f0ty, tyargs, args, m) = + let g = cenv.g // trying to devirtualize match TryDevirtualizeApplication cenv env (f0, tyargs, args, m) with | Some res -> // devirtualized res | None -> - let newf0, finfo = OptimizeFuncInApplication cenv env f0 m + let optf0, finfo = OptimizeFuncInApplication cenv env f0 m + + match StripPreComputationsFromComputedFunction g optf0 args (fun f argsR -> MakeApplicationAndBetaReduce g (f, tyOfExpr g f, [tyargs], argsR, f.Range)) with + | Choice1Of2 remade -> + OptimizeExpr cenv env remade + | Choice2Of2 (newf0, remake) -> + match TryInlineApplication cenv env finfo (tyargs, args, m) with - | Some res -> + | Some (res, info) -> // inlined - res + (res |> remake), info | None -> let shapes = @@ -3017,9 +3156,10 @@ and OptimizeApplication cenv env (f0, f0ty, tyargs, args, m) = let newArgs, arginfos = OptimizeExprsThenReshapeAndConsiderSplits cenv env shapes // beta reducing - let newExpr = MakeApplicationAndBetaReduce cenv.g (newf0, f0ty, [tyargs], newArgs, m) + let reducedExpr = MakeApplicationAndBetaReduce g (newf0, f0ty, [tyargs], newArgs, m) + let newExpr = reducedExpr |> remake - match newf0, newExpr with + match newf0, reducedExpr with | (Expr.Lambda _ | Expr.TyLambda _), Expr.Let _ -> // we beta-reduced, hence reoptimize OptimizeExpr cenv env newExpr @@ -3058,6 +3198,31 @@ and OptimizeApplication cenv env (f0, f0ty, tyargs, args, m) = HasEffect=true MightMakeCriticalTailcall = mayBeCriticalTailcall Info=ValueOfExpr newExpr } + +and OptimizeFSharpDelegateInvoke cenv env (invokeRef, f0, f0ty, tyargs, args, m) = + let g = cenv.g + let optf0, finfo = OptimizeExpr cenv env f0 + + match StripPreComputationsFromComputedFunction g optf0 args (fun f argsR -> MakeFSharpDelegateInvokeAndTryBetaReduce g (invokeRef, f, f0ty, tyargs, argsR, m)) with + | Choice1Of2 remade -> + OptimizeExpr cenv env remade + | Choice2Of2 (newf0, remake) -> + + let newArgs, arginfos = OptimizeExprsThenConsiderSplits cenv env args + let reducedExpr = MakeFSharpDelegateInvokeAndTryBetaReduce g (invokeRef, newf0, f0ty, tyargs, newArgs, m) + let newExpr = reducedExpr |> remake + match newf0, reducedExpr with + | Expr.Obj _, Expr.Let _ -> + // we beta-reduced, hence reoptimize + OptimizeExpr cenv env newExpr + | _ -> + // no reduction, return + newExpr, { TotalSize=finfo.TotalSize + AddTotalSizes arginfos + FunctionSize=finfo.FunctionSize + AddFunctionSizes arginfos + HasEffect=true + MightMakeCriticalTailcall = true + Info=ValueOfExpr newExpr } + /// Optimize/analyze a lambda expression and OptimizeLambdas (vspec: Val option) cenv env topValInfo e ety = @@ -3125,8 +3290,23 @@ and OptimizeLambdas (vspec: Val option) cenv env topValInfo e ety = HasEffect=false MightMakeCriticalTailcall = false Info= valu } + | _ -> OptimizeExpr cenv env e +and OptimizeNewDelegateExpr cenv env (lambdaId, vsl, body, remake) = + let env = List.foldBack (BindInternalValsToUnknown cenv) vsl env + let bodyR, bodyinfo = OptimizeExpr cenv env body + let arities = vsl.Length + let bsize = bodyinfo.TotalSize + let exprR = remake bodyR + let valu = CurriedLambdaValue (lambdaId, arities, bsize, exprR, tyOfExpr cenv.g exprR) + + exprR, { TotalSize=bsize + closureTotalSize (* estimate size of new syntactic closure - expensive, in contrast to a method *) + FunctionSize=1 + HasEffect=false + MightMakeCriticalTailcall = false + Info= valu } + /// Recursive calls that first try to make an expression "fit" the a shape /// where it is about to be consumed. and OptimizeExprsThenReshapeAndConsiderSplits cenv env exprs = @@ -3229,12 +3409,12 @@ and RebuildOptimizedMatch (spMatch, exprm, m, ty, dtree, tgs, dinfo, tinfos) = expr, einfo /// Optimize/analyze a target of a decision tree -and OptimizeDecisionTreeTarget cenv env _m (TTarget(vs, expr, spTarget)) = +and OptimizeDecisionTreeTarget cenv env _m (TTarget(vs, expr, spTarget, flags)) = let env = BindInternalValsToUnknown cenv vs env let exprR, einfo = OptimizeExpr cenv env expr let exprR, einfo = ConsiderSplitToMethod cenv.settings.abstractBigTargets cenv.settings.bigTargetSize cenv env (exprR, einfo) let evalueR = AbstractExprInfoByVars (vs, []) einfo.Info - TTarget(vs, exprR, spTarget), + TTarget(vs, exprR, spTarget, flags), { TotalSize=einfo.TotalSize FunctionSize=einfo.FunctionSize HasEffect=einfo.HasEffect @@ -3333,7 +3513,7 @@ and OptimizeBinding cenv isRec env (TBind(vref, expr, spBind)) = let exprOptimized, einfo = let env = if vref.IsCompilerGenerated && Option.isSome env.latestBoundId then env else {env with latestBoundId=Some vref.Id} - let cenv = if vref.InlineInfo = ValInline.PseudoVal then { cenv with optimizing=false} else cenv + let cenv = if vref.InlineInfo.MustInline then { cenv with optimizing=false} else cenv let arityInfo = InferArityOfExprBinding cenv.g AllowTypeDirectedDetupling.No vref expr let exprOptimized, einfo = OptimizeLambdas (Some vref) cenv env arityInfo expr vref.Type let size = localVarSize @@ -3362,10 +3542,10 @@ and OptimizeBinding cenv isRec env (TBind(vref, expr, spBind)) = | UnknownValue | ConstValue _ | ConstExprValue _ -> ivalue | SizeValue(_, a) -> MakeSizedValueInfo (cut a) - let einfo = if vref.MustInline then einfo else {einfo with Info = cut einfo.Info } + let einfo = if vref.MustInline || vref.InlineIfLambda then einfo else {einfo with Info = cut einfo.Info } let einfo = - if (not vref.MustInline && not (cenv.settings.KeepOptimizationValues())) || + if (not vref.MustInline && not vref.InlineIfLambda && not (cenv.settings.KeepOptimizationValues())) || // Bug 4916: do not record inline data for initialization trigger expressions // Note: we can't eliminate these value infos at the file boundaries because that would change initialization diff --git a/src/fsharp/PatternMatchCompilation.fs b/src/fsharp/PatternMatchCompilation.fs index 403995686d9..8c717e790a4 100644 --- a/src/fsharp/PatternMatchCompilation.fs +++ b/src/fsharp/PatternMatchCompilation.fs @@ -80,7 +80,7 @@ and TypedMatchClause = member c.Pattern = let (TClause(p, _, _, _)) = c in p member c.Range = let (TClause(_, _, _, m)) = c in m member c.Target = let (TClause(_, _, tg, _)) = c in tg - member c.BoundVals = let (TClause(_p, _whenOpt, TTarget(vs, _, _), _m)) = c in vs + member c.BoundVals = let (TClause(_p, _whenOpt, TTarget(vs, _, _, _), _m)) = c in vs let debug = false @@ -854,7 +854,7 @@ let CompilePatternBasic // Note we don't emit sequence points at either the succeeding or failing targets of filters since if // the exception is filtered successfully then we will run the handler and hit the sequence point there. // That sequence point will have the pattern variables bound, which is exactly what we want. - let tg = TTarget(List.empty, throwExpr, DebugPointForTarget.No) + let tg = TTarget([], throwExpr, DebugPointForTarget.No, None) let _ = matchBuilder.AddTarget tg let clause = TClause(TPat_wild matchm, None, tg, matchm) incompleteMatchClauseOnce <- Some clause @@ -871,7 +871,9 @@ let CompilePatternBasic clausesA.[i] elif i = nClauses then getIncompleteMatchClause refuted else failwith "GetClause" + let GetValsBoundByClause i refuted = (GetClause i refuted).BoundVals + let GetWhenGuardOfClause i refuted = (GetClause i refuted).GuardExpr // Different uses of parameterized active patterns have different identities as far as paths are concerned. @@ -1424,7 +1426,7 @@ let rec CompilePattern g denv amap tcVal infoReader exprm matchm warnOnUnused a else DebugPointForTarget.Yes // Make the clause that represents the remaining cases of the pattern match - let clauseForRestOfMatch = TClause(TPat_wild matchm, None, TTarget(List.empty, expr, spTarget), matchm) + let clauseForRestOfMatch = TClause(TPat_wild matchm, None, TTarget(List.empty, expr, spTarget, None), matchm) CompilePatternBasic g denv amap tcVal infoReader exprm matchm warnOnUnused warnOnIncomplete actionOnFailure (origInputVal, origInputValTypars, origInputExprOpt) (group @ [clauseForRestOfMatch]) inputTy resultTy diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index 6008120291e..64c200f4d9e 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -66,6 +66,15 @@ open FSharp.Compiler.TypeRelations // check environment //-------------------------------------------------------------------------- +[] +type Resumable = + | None + /// Indicates we are expecting resumable code (the body of a ResumableCode delegate or + /// the body of the MoveNextMethod for a state machine) + /// -- allowed: are we inside the 'then' branch of an 'if __useResumableCode then ...' + /// for a ResumableCode delegate. + | ResumableExpr of allowed: bool + type env = { /// The bound type parameter names in scope @@ -97,6 +106,9 @@ type env = /// Are we in an app expression (Expr.App)? isInAppExpr: bool + + /// Are we expecting a resumable code block etc + resumableCode: Resumable } override _.ToString() = "" @@ -980,6 +992,99 @@ and CheckExprLinear (cenv: cenv) (env: env) expr (context: PermitByRefExpr) (con // not a linear expression contf (CheckExpr cenv env expr context) +/// Check a resumable code expression (the body of a ResumableCode delegate or +/// the body of the MoveNextMethod for a state machine) +and TryCheckResumableCodeConstructs cenv env expr : bool = + let g = cenv.g + + match env.resumableCode with + | Resumable.None -> + CheckNoResumableStmtConstructs cenv env expr + false + | Resumable.ResumableExpr allowed -> + match expr with + | IfUseResumableStateMachinesExpr g (thenExpr, elseExpr) -> + CheckExprNoByrefs cenv { env with resumableCode = Resumable.ResumableExpr true } thenExpr + CheckExprNoByrefs cenv { env with resumableCode = Resumable.None } elseExpr + true + + | ResumableEntryMatchExpr g (noneBranchExpr, someVar, someBranchExpr, _rebuild) -> + if not allowed then + errorR(Error(FSComp.SR.tcInvalidResumableConstruct("__resumableEntry"), expr.Range)) + CheckExprNoByrefs cenv env noneBranchExpr + BindVal cenv env someVar + CheckExprNoByrefs cenv env someBranchExpr + true + + | ResumeAtExpr g pcExpr -> + if not allowed then + errorR(Error(FSComp.SR.tcInvalidResumableConstruct("__resumeAt"), expr.Range)) + CheckExprNoByrefs cenv env pcExpr + true + + | ResumableCodeInvoke g (_, f, args, _, _) -> + CheckExprNoByrefs cenv { env with resumableCode = Resumable.None } f + for arg in args do + CheckExprPermitByRefLike cenv { env with resumableCode = Resumable.None } arg |> ignore + true + + | SequentialResumableCode g (e1, e2, _m, _recreate) -> + CheckExprNoByrefs cenv { env with resumableCode = Resumable.ResumableExpr allowed }e1 + CheckExprNoByrefs cenv env e2 + true + + | WhileExpr (_sp1, _sp2, guardExpr, bodyExpr, _m) -> + CheckExprNoByrefs cenv { env with resumableCode = Resumable.None } guardExpr + CheckExprNoByrefs cenv env bodyExpr + true + + // Integer for-loops are allowed but their bodies are not currently resumable + | ForLoopExpr (_sp1, _sp2, e1, e2, v, e3, _m) -> + CheckExprNoByrefs cenv { env with resumableCode = Resumable.None } e1 + CheckExprNoByrefs cenv { env with resumableCode = Resumable.None } e2 + BindVal cenv env v + CheckExprNoByrefs cenv { env with resumableCode = Resumable.None } e3 + true + + | TryWithExpr (_spTry, _spWith, _resTy, bodyExpr, _filterVar, filterExpr, _handlerVar, handlerExpr, _m) -> + CheckExprNoByrefs cenv env bodyExpr + CheckExprNoByrefs cenv { env with resumableCode = Resumable.None } handlerExpr + CheckExprNoByrefs cenv { env with resumableCode = Resumable.None } filterExpr + true + + | TryFinallyExpr (_sp1, _sp2, _ty, e1, e2, _m) -> + CheckExprNoByrefs cenv { env with resumableCode = Resumable.None } e1 + CheckExprNoByrefs cenv { env with resumableCode = Resumable.None } e2 + true + + | Expr.Match (_spBind, _exprm, dtree, targets, _m, _ty) -> + targets |> Array.iter(fun (TTarget(vs, targetExpr, _spTarget, _)) -> + BindVals cenv env vs + CheckExprNoByrefs cenv env targetExpr) + CheckDecisionTree cenv { env with resumableCode = Resumable.None } dtree + true + + | Expr.Let (bind, bodyExpr, _m, _) + // Restriction: resumable code can't contain local constrained generic functions + when bind.Var.IsCompiledAsTopLevel || not (IsGenericValWithGenericConstraints g bind.Var) -> + CheckBinding cenv { env with resumableCode = Resumable.None } false PermitByRefExpr.Yes bind |> ignore + BindVal cenv env bind.Var + CheckExprNoByrefs cenv env bodyExpr + true + + // LetRec bindings may not appear as part of resumable code (more careful work is needed to make them compilable) + | Expr.LetRec(_bindings, bodyExpr, _range, _frees) when allowed -> + errorR(Error(FSComp.SR.tcResumableCodeContainsLetRec(), expr.Range)) + CheckExprNoByrefs cenv env bodyExpr + true + + // This construct arises from the 'mkDefault' in the 'Throw' case of an incomplete pattern match + | Expr.Const (Const.Zero, _, _) -> + true + + | _ -> + false + /// Check an expression, given information about the position of the expression and CheckExpr (cenv: cenv) (env: env) origExpr (context: PermitByRefExpr) : Limit = let g = cenv.g @@ -991,6 +1096,15 @@ and CheckExpr (cenv: cenv) (env: env) origExpr (context: PermitByRefExpr) : Limi let expr = NormalizeAndAdjustPossibleSubsumptionExprs g origExpr let expr = stripExpr expr + match TryCheckResumableCodeConstructs cenv env expr with + | true -> + // we've handled the special cases of resumable code and don't do other checks. + NoLimit + | false -> + + // Handle ResumableExpr --> other expression + let env = { env with resumableCode = Resumable.None } + match expr with | LinearOpExpr _ | LinearMatchExpr _ @@ -1034,9 +1148,22 @@ and CheckExpr (cenv: cenv) (env: env) origExpr (context: PermitByRefExpr) : Limi CheckTypeNoByrefs cenv env m ty NoLimit + | StructStateMachineExpr g (_dataTy, + (moveNextThisVar, moveNextExpr), + (setStateMachineThisVar, setStateMachineStateVar, setStateMachineBody), + (afterCodeThisVar, afterCodeBody)) -> + if not (g.langVersion.SupportsFeature LanguageFeature.ResumableStateMachines) then + error(Error(FSComp.SR.tcResumableCodeNotSupported(), expr.Range)) + + BindVals cenv env [moveNextThisVar; setStateMachineThisVar; setStateMachineStateVar; afterCodeThisVar] + CheckExprNoByrefs cenv { env with resumableCode = Resumable.ResumableExpr true } moveNextExpr + CheckExprNoByrefs cenv env setStateMachineBody + CheckExprNoByrefs cenv env afterCodeBody + NoLimit + | Expr.Obj (_, ty, basev, superInitCall, overrides, iimpls, m) -> CheckExprNoByrefs cenv env superInitCall - CheckMethods cenv env basev overrides + CheckMethods cenv env basev (ty, overrides) CheckInterfaceImpls cenv env basev iimpls CheckTypeNoByrefs cenv env m ty @@ -1113,6 +1240,11 @@ and CheckExpr (cenv: cenv) (env: env) origExpr (context: PermitByRefExpr) : Limi // Check an application | Expr.App (f, _fty, tyargs, argsl, m) -> + match expr with + | ResumableCodeInvoke g _ -> + warning(Error(FSComp.SR.tcResumableCodeInvocation(), m)) + | _ -> () + let returnTy = tyOfExpr g expr // This is to handle recursive cases. Don't check 'returnTy' again if we are still inside a app expression. @@ -1178,13 +1310,21 @@ and CheckExpr (cenv: cenv) (env: env) origExpr (context: PermitByRefExpr) : Limi | Expr.Link _ -> failwith "Unexpected reclink" -and CheckMethods cenv env baseValOpt methods = - methods |> List.iter (CheckMethod cenv env baseValOpt) +and CheckMethods cenv env baseValOpt (ty, methods) = + methods |> List.iter (CheckMethod cenv env baseValOpt ty) -and CheckMethod cenv env baseValOpt (TObjExprMethod(_, attribs, tps, vs, body, m)) = +and CheckMethod cenv env baseValOpt ty (TObjExprMethod(_, attribs, tps, vs, body, m)) = let env = BindTypars cenv.g env tps let vs = List.concat vs let env = BindArgVals env vs + let env = + // Body of ResumableCode delegate + if isResumableCodeTy cenv.g ty then + if not (cenv.g.langVersion.SupportsFeature LanguageFeature.ResumableStateMachines) then + error(Error(FSComp.SR.tcResumableCodeNotSupported(), m)) + { env with resumableCode = Resumable.ResumableExpr false } + else + { env with resumableCode = Resumable.None } CheckAttribs cenv env attribs CheckNoReraise cenv None body CheckEscapes cenv true m (match baseValOpt with Some x -> x :: vs | None -> vs) body |> ignore @@ -1193,11 +1333,22 @@ and CheckMethod cenv env baseValOpt (TObjExprMethod(_, attribs, tps, vs, body, m and CheckInterfaceImpls cenv env baseValOpt l = l |> List.iter (CheckInterfaceImpl cenv env baseValOpt) -and CheckInterfaceImpl cenv env baseValOpt (_ty, overrides) = +and CheckInterfaceImpl cenv env baseValOpt overrides = CheckMethods cenv env baseValOpt overrides +and CheckNoResumableStmtConstructs cenv _env expr = + let g = cenv.g + match expr with + | Expr.Val (v, _, m) + when valRefEq g v g.cgh__resumeAt_vref || + valRefEq g v g.cgh__resumableEntry_vref || + valRefEq g v g.cgh__stateMachine_vref -> + errorR(Error(FSComp.SR.tcInvalidResumableConstruct(v.DisplayName), m)) + | _ -> () + and CheckExprOp cenv env (op, tyargs, args, m) context expr = let g = cenv.g + let ctorLimitedZoneCheck() = if env.ctorLimitedZone then errorR(Error(FSComp.SR.chkObjCtorsCantUseExceptionHandling(), m)) @@ -1475,18 +1626,20 @@ and CheckExprOp cenv env (op, tyargs, args, m) context expr = CheckTypeInstNoByrefs cenv env m tyargs CheckExprsNoByRefLike cenv env args -and CheckLambdas isTop (memInfo: ValMemberInfo option) cenv env inlined topValInfo alwaysCheckNoReraise e mOrig ety context = +and CheckLambdas isTop (memberVal: Val option) cenv env inlined topValInfo alwaysCheckNoReraise expr mOrig ety context = let g = cenv.g + let memInfo = memberVal |> Option.bind (fun v -> v.MemberInfo) + // The topValInfo here says we are _guaranteeing_ to compile a function value // as a .NET method with precisely the corresponding argument counts. - match e with + match expr with | Expr.TyChoose (tps, e1, m) -> let env = BindTypars g env tps - CheckLambdas isTop memInfo cenv env inlined topValInfo alwaysCheckNoReraise e1 m ety context + CheckLambdas isTop memberVal cenv env inlined topValInfo alwaysCheckNoReraise e1 m ety context | Expr.Lambda (_, _, _, _, _, m, _) | Expr.TyLambda (_, _, _, m, _) -> - let tps, ctorThisValOpt, baseValOpt, vsl, body, bodyty = destTopLambda g cenv.amap topValInfo (e, ety) in + let tps, ctorThisValOpt, baseValOpt, vsl, body, bodyty = destTopLambda g cenv.amap topValInfo (expr, ety) let env = BindTypars g env tps let thisAndBase = Option.toList ctorThisValOpt @ Option.toList baseValOpt let restArgs = List.concat vsl @@ -1514,6 +1667,9 @@ and CheckLambdas isTop (memInfo: ValMemberInfo option) cenv env inlined topValIn // Check argument types syntacticArgs |> List.iter (fun arg -> + if arg.InlineIfLambda && (not inlined || not (isFunTy g arg.Type || isFSharpDelegateTy g arg.Type)) then + errorR(Error(FSComp.SR.tcInlineIfLambdaUsedOnNonInlineFunctionOrMethod(), arg.Range)) + CheckValSpecAux permitByRefType cenv env arg (fun () -> if arg.IsCompilerGenerated then errorR(Error(FSComp.SR.chkErrorUseOfByref(), arg.Range)) @@ -1568,13 +1724,13 @@ and CheckLambdas isTop (memInfo: ValMemberInfo option) cenv env inlined topValIn let limit = if not inlined && (isByrefLikeTy g m ety || isNativePtrTy g ety) then // allow byref to occur as RHS of byref binding. - CheckExpr cenv env e context + CheckExpr cenv env expr context else - CheckExprNoByrefs cenv env e + CheckExprNoByrefs cenv env expr NoLimit if alwaysCheckNoReraise then - CheckNoReraise cenv None e + CheckNoReraise cenv None expr limit and CheckExprs cenv env exprs contexts : Limit = @@ -1588,7 +1744,7 @@ and CheckExprsNoByRefLike cenv env exprs : Limit = exprs |> List.iter (CheckExprNoByrefs cenv env) NoLimit -and CheckExprsPermitByRefLike cenv env exprs = +and CheckExprsPermitByRefLike cenv env exprs : Limit = exprs |> List.map (CheckExprPermitByRefLike cenv env) |> CombineLimits @@ -1609,7 +1765,7 @@ and CheckDecisionTreeTargets cenv env targets context = |> Array.map (CheckDecisionTreeTarget cenv env context) |> (CombineLimits << List.ofArray) -and CheckDecisionTreeTarget cenv env context (TTarget(vs, e, _)) = +and CheckDecisionTreeTarget cenv env context (TTarget(vs, e, _, _)) = BindVals cenv env vs vs |> List.iter (CheckValSpec PermitByRefType.All cenv env) CheckExpr cenv env e context @@ -1838,7 +1994,23 @@ and CheckBinding cenv env alwaysCheckNoReraise context (TBind(v, bindRhs, _) as let topValInfo = match bind.Var.ValReprInfo with Some info -> info | _ -> ValReprInfo.emptyValData - CheckLambdas isTop v.MemberInfo cenv env v.MustInline topValInfo alwaysCheckNoReraise bindRhs v.Range v.Type context + // If the method has ResumableCode argument or return type it must be inline + // unless warning is suppressed (user must know what they're doing). + // + // If the method has ResumableCode return attribute we check the body w.r.t. that + let env = + if cenv.reportErrors && isReturnsResumableCodeTy g v.TauType then + if not (g.langVersion.SupportsFeature LanguageFeature.ResumableStateMachines) then + error(Error(FSComp.SR.tcResumableCodeNotSupported(), bind.Var.Range)) + if not v.MustInline then + warning(Error(FSComp.SR.tcResumableCodeFunctionMustBeInline(), v.Range)) + + if isReturnsResumableCodeTy g v.TauType then + { env with resumableCode = Resumable.ResumableExpr false } + else + env + + CheckLambdas isTop (Some v) cenv env v.MustInline topValInfo alwaysCheckNoReraise bindRhs v.Range v.Type context and CheckBindings cenv env xs = xs |> List.iter (CheckBinding cenv env false PermitByRefExpr.Yes >> ignore) @@ -2355,8 +2527,8 @@ let CheckTopImpl (g, amap, reportErrors, infoReader, internalsVisibleToPaths, vi let cenv = { g =g reportErrors=reportErrors - boundVals= new Dictionary<_, _>(100, HashIdentity.Structural) - limitVals= new Dictionary<_, _>(100, HashIdentity.Structural) + boundVals = Dictionary<_, _>(100, HashIdentity.Structural) + limitVals = Dictionary<_, _>(100, HashIdentity.Structural) potentialUnboundUsesOfVals=Map.empty anonRecdTypes = StampMap.Empty usesQuotations=false @@ -2391,7 +2563,8 @@ let CheckTopImpl (g, amap, reportErrors, infoReader, internalsVisibleToPaths, vi reflect=false external=false returnScope = 0 - isInAppExpr = false } + isInAppExpr = false + resumableCode = Resumable.None } CheckModuleExpr cenv env mexpr CheckAttribs cenv env extraAttribs diff --git a/src/fsharp/PrettyNaming.fs b/src/fsharp/PrettyNaming.fs index 8bdcd36e120..e6072ad62c5 100755 --- a/src/fsharp/PrettyNaming.fs +++ b/src/fsharp/PrettyNaming.fs @@ -769,3 +769,9 @@ let FSharpOptimizationDataResourceName2 = "FSharpOptimizationInfo." let FSharpSignatureDataResourceName2 = "FSharpSignatureInfo." +let [] suffixForVariablesThatMayNotBeEliminated = "$cont" + +let [] suffixForTupleElementAssignmentTarget = "$tupleElem" + +let [] stackVarPrefix = "__stack_" + diff --git a/src/fsharp/PrettyNaming.fsi b/src/fsharp/PrettyNaming.fsi index 8c67b0ceb4f..e03cf533e53 100644 --- a/src/fsharp/PrettyNaming.fsi +++ b/src/fsharp/PrettyNaming.fsi @@ -180,3 +180,16 @@ val GetLongNameFromString: string -> string list val FormatAndOtherOverloadsString: int -> string +val FSharpSignatureDataResourceName2: string + +/// Mark some variables (the ones we introduce via abstractBigTargets) as don't-eliminate +[] +val internal suffixForVariablesThatMayNotBeEliminated : string = "$cont" + +/// Indicates a ValRef generated to facilitate tuple eliminations +[] +val internal suffixForTupleElementAssignmentTarget : string = "$tupleElem" + +[] +val internal stackVarPrefix : string = "__stack_" + diff --git a/src/fsharp/QuotationTranslator.fs b/src/fsharp/QuotationTranslator.fs index 166d62a0b6f..9ae96ba19b7 100644 --- a/src/fsharp/QuotationTranslator.fs +++ b/src/fsharp/QuotationTranslator.fs @@ -203,7 +203,7 @@ let (|ObjectInitializationCheck|_|) g expr = ( Expr.Op (TOp.ILAsm ([AI_clt], _), _, [Expr.Op (TOp.ValFieldGet ((RecdFieldRef(_, name))), _, [Expr.Val (selfRef, NormalValUse, _)], _); Expr.Const (Const.Int32 1, _, _)], _), _, _, _ ), - [| TTarget([], Expr.App (Expr.Val (failInitRef, _, _), _, _, _, _), _); _ |], _, resultTy + [| TTarget([], Expr.App (Expr.Val (failInitRef, _, _), _, _, _, _), _, _); _ |], _, resultTy ) when IsCompilerGeneratedName name && name.StartsWithOrdinal("init") && @@ -479,7 +479,6 @@ and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP. let typR = ConvType cenv env m retTy ConvDecisionTree cenv env tgs typR dtree - // initialization check | Expr.Sequential (ObjectInitializationCheck g, x1, NormalSeq, _, _) -> ConvExpr cenv env x1 @@ -816,7 +815,7 @@ and ConvLValueArgs cenv env args = | obj :: rest -> ConvLValueExpr cenv env obj :: ConvExprs cenv env rest | [] -> [] -and ConvLValueExpr cenv env expr = +and ConvLValueExpr cenv env (expr: Expr) = EmitDebugInfoIfNecessary cenv env expr.Range (ConvLValueExprCore cenv env expr) // This function has to undo the work of mkExprAddrOfExpr @@ -1105,7 +1104,7 @@ and ConvDecisionTree cenv env tgs typR x = EmitDebugInfoIfNecessary cenv env m converted | TDSuccess (args, n) -> - let (TTarget(vars, rhs, _)) = tgs.[n] + let (TTarget(vars, rhs, _, _)) = tgs.[n] // TAST stores pattern bindings in reverse order for some reason // Reverse them here to give a good presentation to the user let args = List.rev args diff --git a/src/fsharp/SignatureConformance.fs b/src/fsharp/SignatureConformance.fs index af0fe7fd5fe..583092b10f5 100644 --- a/src/fsharp/SignatureConformance.fs +++ b/src/fsharp/SignatureConformance.fs @@ -293,6 +293,15 @@ type Checker(g, amap, denv, remapInfo: SignatureRepackageInfo, checkingSig) = warning(Error (FSComp.SR.ArgumentsInSigAndImplMismatch(sname.idText, iname.idText), iname.idRange)) | _ -> () + let sigHasInlineIfLambda = HasFSharpAttribute g g.attrib_InlineIfLambdaAttribute sigArgInfo.Attribs + let implHasInlineIfLambda = HasFSharpAttribute g g.attrib_InlineIfLambdaAttribute implArgInfo.Attribs + let m = + match implArgInfo.Name with + | Some iname-> iname.idRange + | None -> implVal.Range + if sigHasInlineIfLambda && not implHasInlineIfLambda then + errorR(Error (FSComp.SR.implMissingInlineIfLambda(), m)) + implArgInfo.Name <- sigArgInfo.Name implArgInfo.Attribs <- attribs))) && diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index 06e1b054ba0..2b0614261ed 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -175,11 +175,10 @@ type DebugPointForTarget = [] type DebugPointAtSequential = - | Both - - | StmtOnly - - | ExprOnly + | SuppressNeither + | SuppressStmt + | SuppressBoth + | SuppressExpr [] type DebugPointAtTry = @@ -509,13 +508,13 @@ type SynExpr = range: range | While of - whileSeqPoint: DebugPointAtWhile * + whileDebugPoint: DebugPointAtWhile * whileExpr: SynExpr * doExpr: SynExpr * range: range | For of - forSeqPoint: DebugPointAtFor * + forDebugPoint: DebugPointAtFor * ident: Ident * identBody: SynExpr * direction: bool * @@ -524,7 +523,7 @@ type SynExpr = range: range | ForEach of - forSeqPoint: DebugPointAtFor * + forDebugPoint: DebugPointAtFor * seqExprOnly: SeqExprOnly * isFromSource: bool * pat: SynPat * @@ -555,11 +554,11 @@ type SynExpr = isExnMatch: bool * keywordRange: range * matchClauses: SynMatchClause list * - matchSeqPoint: DebugPointAtBinding * + matchDebugPoint: DebugPointAtBinding * range: range | Match of - matchSeqPoint: DebugPointAtBinding * + matchDebugPoint: DebugPointAtBinding * expr: SynExpr * clauses: SynMatchClause list * range: range @@ -601,22 +600,22 @@ type SynExpr = withCases: SynMatchClause list * withRange: range * range: range * - trySeqPoint: DebugPointAtTry * - withSeqPoint: DebugPointAtWith + tryDebugPoint: DebugPointAtTry * + withDebugPoint: DebugPointAtWith | TryFinally of tryExpr: SynExpr * finallyExpr: SynExpr * range: range * - trySeqPoint: DebugPointAtTry * - finallySeqPoint: DebugPointAtFinally + tryDebugPoint: DebugPointAtTry * + finallyDebugPoint: DebugPointAtFinally | Lazy of expr: SynExpr * range: range | Sequential of - seqPoint: DebugPointAtSequential * + debugPoint: DebugPointAtSequential * isTrueSeq: bool * expr1: SynExpr * expr2: SynExpr * @@ -737,7 +736,7 @@ type SynExpr = range: range | SequentialOrImplicitYield of - seqPoint:DebugPointAtSequential * + debugPoint:DebugPointAtSequential * expr1:SynExpr * expr2:SynExpr * ifNotStmt:SynExpr * @@ -754,7 +753,7 @@ type SynExpr = range: range | LetOrUseBang of - bindSeqPoint: DebugPointAtBinding * + bindDebugPoint: DebugPointAtBinding * isUse: bool * isFromSource: bool * pat: SynPat * @@ -764,7 +763,7 @@ type SynExpr = range: range | MatchBang of - matchSeqPoint: DebugPointAtBinding * + matchDebugPoint: DebugPointAtBinding * expr: SynExpr * clauses: SynMatchClause list * range: range @@ -948,8 +947,8 @@ type SynSimplePat = ident: Ident * altNameRefCell: SynSimplePatAlternativeIdInfo ref option * isCompilerGenerated: bool * - isThisVar: bool * - isOptArg: bool * + isThisVal: bool * + isOptional: bool * range: range | Typed of @@ -1024,7 +1023,7 @@ type SynPat = | Named of ident: Ident * - isSelfIdentifier: bool * + isThisVal: bool * accessibility: SynAccess option * range: range @@ -1146,7 +1145,7 @@ type SynMatchClause = whenExpr: SynExpr option * resultExpr: SynExpr * range: range * - spInfo: DebugPointForTarget + debugPoint: DebugPointForTarget member this.RangeOfGuardAndRhs = match this with @@ -1196,7 +1195,7 @@ type SynBinding = | SynBinding of accessibility: SynAccess option * kind: SynBindingKind * - mustInline: bool * + isInline: bool * isMutable: bool * attributes: SynAttributes * xmlDoc: PreXmlDoc * @@ -1205,7 +1204,7 @@ type SynBinding = returnInfo: SynBindingReturnInfo option * expr: SynExpr * range: range * - seqPoint: DebugPointAtBinding + debugPoint: DebugPointAtBinding // no member just named "Range", as that would be confusing: // - for everything else, the 'range' member that appears last/second-to-last is the 'full range' of the whole tree construct @@ -1499,6 +1498,8 @@ type SynArgInfo = member x.Ident : Ident option = let (SynArgInfo(_,_,id)) = x in id + member x.Attributes : SynAttributes = let (SynArgInfo(attrs,_,_)) = x in attrs + [] type SynValTyparDecls = | SynValTyparDecls of @@ -1673,7 +1674,7 @@ type SynModuleDecl = range: range | DoExpr of - spInfo: DebugPointAtBinding * + debugPoint: DebugPointAtBinding * expr: SynExpr * range: range diff --git a/src/fsharp/SyntaxTree.fsi b/src/fsharp/SyntaxTree.fsi index 4a82c325a5f..88159770cfd 100644 --- a/src/fsharp/SyntaxTree.fsi +++ b/src/fsharp/SyntaxTree.fsi @@ -218,18 +218,21 @@ type DebugPointForTarget = | Yes | No -/// Represents whether a debug point should be present for either the +/// Represents whether a debug point should be suppressed for either the /// first or second part of a sequential execution, that is whether the /// construct corresponds to a debug point in the original source. [] type DebugPointAtSequential = - | Both + | SuppressNeither // This means "suppress a in 'a;b'" and "suppress b in 'a before b'" - | StmtOnly + | SuppressStmt + + // This means "suppress both" + | SuppressBoth // This means "suppress b in 'a;b'" and "suppress a in 'a before b'" - | ExprOnly + | SuppressExpr /// Represents whether a debug point should be present for a 'try', that is whether /// the construct corresponds to a debug point in the original source. @@ -615,14 +618,14 @@ type SynExpr = /// F# syntax: 'while ... do ...' | While of - whileSeqPoint: DebugPointAtWhile * + whileDebugPoint: DebugPointAtWhile * whileExpr: SynExpr * doExpr: SynExpr * range: range /// F# syntax: 'for i = ... to ... do ...' | For of - forSeqPoint: DebugPointAtFor * + forDebugPoint: DebugPointAtFor * ident: Ident * identBody: SynExpr * direction: bool * @@ -632,7 +635,7 @@ type SynExpr = /// F# syntax: 'for ... in ... do ...' | ForEach of - forSeqPoint: DebugPointAtFor * + forDebugPoint: DebugPointAtFor * seqExprOnly: SeqExprOnly * isFromSource: bool * pat: SynPat * @@ -672,12 +675,12 @@ type SynExpr = isExnMatch: bool * keywordRange: range * matchClauses: SynMatchClause list * - matchSeqPoint: DebugPointAtBinding * + matchDebugPoint: DebugPointAtBinding * range: range /// F# syntax: match expr with pat1 -> expr | ... | patN -> exprN | Match of - matchSeqPoint: DebugPointAtBinding * + matchDebugPoint: DebugPointAtBinding * expr: SynExpr * clauses: SynMatchClause list * range: range @@ -732,16 +735,16 @@ type SynExpr = withCases: SynMatchClause list * withRange: range * range: range * - trySeqPoint: DebugPointAtTry * - withSeqPoint: DebugPointAtWith + tryDebugPoint: DebugPointAtTry * + withDebugPoint: DebugPointAtWith /// F# syntax: try expr finally expr | TryFinally of tryExpr: SynExpr * finallyExpr: SynExpr * range: range * - trySeqPoint: DebugPointAtTry * - finallySeqPoint: DebugPointAtFinally + tryDebugPoint: DebugPointAtTry * + finallyDebugPoint: DebugPointAtFinally /// F# syntax: lazy expr | Lazy of @@ -752,7 +755,7 @@ type SynExpr = /// /// isTrueSeq: false indicates "let v = a in b; v" | Sequential of - seqPoint: DebugPointAtSequential * + debugPoint: DebugPointAtSequential * isTrueSeq: bool * expr1: SynExpr * expr2: SynExpr * @@ -902,7 +905,7 @@ type SynExpr = /// Used internally during type checking for translating computation expressions. | SequentialOrImplicitYield of - seqPoint:DebugPointAtSequential * + debugPoint:DebugPointAtSequential * expr1:SynExpr * expr2:SynExpr * ifNotStmt:SynExpr * @@ -929,7 +932,7 @@ type SynExpr = /// F# syntax: let! pat = expr and! ... and! ... and! pat = expr in expr /// Computation expressions only | LetOrUseBang of - bindSeqPoint: DebugPointAtBinding * + bindDebugPoint: DebugPointAtBinding * isUse: bool * isFromSource: bool * pat: SynPat * @@ -940,7 +943,7 @@ type SynExpr = /// F# syntax: match! expr with pat1 -> expr | ... | patN -> exprN | MatchBang of - matchSeqPoint: DebugPointAtBinding * + matchDebugPoint: DebugPointAtBinding * expr: SynExpr * clauses: SynMatchClause list * range: range @@ -1062,14 +1065,14 @@ type SynSimplePat = /// name of the identifier is already bound. /// /// isCompilerGenerated: true if a compiler generated name - /// isThisVar: true if 'this' variable in member - /// isOptArg: true if a '?' is in front of the name + /// isThisVal: true if 'this' variable in member + /// isOptional: true if a '?' is in front of the name | Id of ident: Ident * altNameRefCell: SynSimplePatAlternativeIdInfo ref option * isCompilerGenerated: bool * - isThisVar: bool * - isOptArg: bool * + isThisVal: bool * + isOptional: bool * range: range /// A type annotated simple pattern @@ -1151,11 +1154,10 @@ type SynPat = | Wild of range: range - /// A name pattern 'ident' but @dsyme wants to keep the old name "named" - /// when this double-purposed to also represent 'pat as ident' to reduce churn + /// A name pattern 'ident' | Named of ident: Ident * - isSelfIdentifier: bool * + isThisVal: bool * accessibility: SynAccess option * range: range @@ -1276,7 +1278,7 @@ type SynMatchClause = whenExpr: SynExpr option * resultExpr: SynExpr * range: range * - spInfo: DebugPointForTarget + debugPoint: DebugPointForTarget /// Gets the syntax range of part of this construct member RangeOfGuardAndRhs: range @@ -1332,7 +1334,7 @@ type SynBinding = | SynBinding of accessibility: SynAccess option * kind: SynBindingKind * - mustInline: bool * + isInline: bool * isMutable: bool * attributes: SynAttributes * xmlDoc: PreXmlDoc * @@ -1341,7 +1343,7 @@ type SynBinding = returnInfo: SynBindingReturnInfo option * expr: SynExpr * range: range * - seqPoint: DebugPointAtBinding + debugPoint: DebugPointAtBinding // no member just named "Range", as that would be confusing: // - for everything else, the 'range' member that appears last/second-to-last is the 'full range' of the whole tree construct @@ -1670,6 +1672,8 @@ type SynArgInfo = member Ident: Ident option + member Attributes: SynAttributes + /// Represents the names and other metadata for the type parameters for a member or function [] type SynValTyparDecls = @@ -1858,7 +1862,7 @@ type SynModuleDecl = /// A 'do expr' within a module | DoExpr of - spInfo: DebugPointAtBinding * + debugPoint: DebugPointAtBinding * expr: SynExpr * range: range diff --git a/src/fsharp/SyntaxTreeOps.fs b/src/fsharp/SyntaxTreeOps.fs index 35f238f00d7..b232a5fe567 100644 --- a/src/fsharp/SyntaxTreeOps.fs +++ b/src/fsharp/SyntaxTreeOps.fs @@ -508,8 +508,9 @@ module SynInfo = /// For 'let' definitions, we infer syntactic argument information from the r.h.s. of a definition, if it /// is an immediate 'fun ... -> ...' or 'function ...' expression. This is noted in the F# language specification. - /// This does not apply to member definitions. - let InferLambdaArgs origRhsExpr = + /// This does not apply to member definitions nor to returns with attributes + let InferLambdaArgs (retInfo: SynArgInfo) origRhsExpr = + if retInfo.Attributes.Length > 0 then [] else let rec loop e = match e with | SynExpr.Lambda (false, _, spats, rest, _, _) -> @@ -545,7 +546,7 @@ module SynInfo = match memberFlagsOpt with | None -> - let infosForLambdaArgs = InferLambdaArgs origRhsExpr + let infosForLambdaArgs = InferLambdaArgs retInfo origRhsExpr let infosForArgs = infosForExplicitArgs @ (if explicitArgsAreSimple then infosForLambdaArgs else []) let infosForArgs = AdjustArgsForUnitElimination infosForArgs SynValData(None, SynValInfo(infosForArgs, retInfo), None) diff --git a/src/fsharp/SyntaxTreeOps.fsi b/src/fsharp/SyntaxTreeOps.fsi index 106b7a61540..2d7fd843011 100644 --- a/src/fsharp/SyntaxTreeOps.fsi +++ b/src/fsharp/SyntaxTreeOps.fsi @@ -226,11 +226,6 @@ module SynInfo = /// rather than member signatures. val AdjustMemberArgs: memFlags:SynMemberKind -> infosForArgs:'a list list -> 'a list list - /// For 'let' definitions, we infer syntactic argument information from the r.h.s. of a definition, if it - /// is an immediate 'fun ... -> ...' or 'function ...' expression. This is noted in the F# language specification. - /// This does not apply to member definitions. - val InferLambdaArgs: origRhsExpr:SynExpr -> SynArgInfo list list - val InferSynReturnData: retInfo:SynReturnInfo option -> SynArgInfo val emptySynValData: SynValData diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index 87b1810fe34..c25d4ce8ecd 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -350,11 +350,10 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let v_FormattableStringFactory_ty = mkNonGenericTy v_FormattableStringFactory_tcref let v_string_ty = mkNonGenericTy v_string_tcr let v_decimal_ty = mkSysNonGenericTy sys "Decimal" - let v_unit_ty = mkNonGenericTy v_unit_tcr_nice - let v_system_Type_ty = mkSysNonGenericTy sys "Type" + let v_unit_ty = mkNonGenericTy v_unit_tcr_nice + let v_system_Type_ty = mkSysNonGenericTy sys "Type" let v_Array_tcref = findSysTyconRef sys "Array" - let v_system_Reflection_MethodInfo_ty = mkSysNonGenericTy ["System";"Reflection"] "MethodInfo" let v_nullable_tcr = findSysTyconRef sys "Nullable`1" @@ -461,6 +460,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let fslib_MFStringModule_nleref = mkNestedNonLocalEntityRef fslib_MFCollections_nleref "StringModule" let fslib_MFNativePtrModule_nleref = mkNestedNonLocalEntityRef fslib_MFNativeInterop_nleref "NativePtrModule" let fslib_MFOptionModule_nleref = mkNestedNonLocalEntityRef fslib_MFCore_nleref "OptionModule" + let fslib_MFStateMachineHelpers_nleref = mkNestedNonLocalEntityRef fslib_MFCompilerServices_nleref "StateMachineHelpers" let fslib_MFRuntimeHelpers_nleref = mkNestedNonLocalEntityRef fslib_MFCompilerServices_nleref "RuntimeHelpers" let fslib_MFQuotations_nleref = mkNestedNonLocalEntityRef fslib_MF_nleref "Quotations" @@ -517,15 +517,16 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d fslib_MFPrintfModule_nleref fslib_MFSeqModule_nleref fslib_MFListModule_nleref - fslib_MFArrayModule_nleref - fslib_MFArray2DModule_nleref - fslib_MFArray3DModule_nleref - fslib_MFArray4DModule_nleref - fslib_MFSetModule_nleref - fslib_MFMapModule_nleref - fslib_MFStringModule_nleref - fslib_MFNativePtrModule_nleref - fslib_MFOptionModule_nleref + fslib_MFArrayModule_nleref + fslib_MFArray2DModule_nleref + fslib_MFArray3DModule_nleref + fslib_MFArray4DModule_nleref + fslib_MFSetModule_nleref + fslib_MFMapModule_nleref + fslib_MFStringModule_nleref + fslib_MFNativePtrModule_nleref + fslib_MFOptionModule_nleref + fslib_MFStateMachineHelpers_nleref fslib_MFRuntimeHelpers_nleref ] do yield nleref.LastItemMangledName, ERefNonLocal nleref ] @@ -719,7 +720,11 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d let v_seq_finally_info = makeIntrinsicValRef(fslib_MFRuntimeHelpers_nleref, "EnumerateThenFinally" , None , None , [varb], ([[mkSeqTy varbTy]; [v_unit_ty --> v_unit_ty]], mkSeqTy varbTy)) let v_seq_of_functions_info = makeIntrinsicValRef(fslib_MFRuntimeHelpers_nleref, "EnumerateFromFunctions" , None , None , [vara;varb], ([[v_unit_ty --> varaTy]; [varaTy --> v_bool_ty]; [varaTy --> varbTy]], mkSeqTy varbTy)) let v_create_event_info = makeIntrinsicValRef(fslib_MFRuntimeHelpers_nleref, "CreateEvent" , None , None , [vara;varb], ([[varaTy --> v_unit_ty]; [varaTy --> v_unit_ty]; [(v_obj_ty --> (varbTy --> v_unit_ty)) --> varaTy]], TType_app (v_fslib_IEvent2_tcr, [varaTy;varbTy]))) - let v_seq_to_array_info = makeIntrinsicValRef(fslib_MFSeqModule_nleref, "toArray" , None , Some "ToArray", [varb], ([[mkSeqTy varbTy]], mkArrayType 1 varbTy)) + let v_cgh__useResumableCode_info = makeIntrinsicValRef(fslib_MFStateMachineHelpers_nleref, "__useResumableCode" , None , None , [vara], ([[]], v_bool_ty)) + let v_cgh__resumeAt_info = makeIntrinsicValRef(fslib_MFStateMachineHelpers_nleref, "__resumeAt" , None , None , [vara], ([[v_int_ty]; [varaTy]], varaTy)) + let v_cgh__stateMachine_info = makeIntrinsicValRef(fslib_MFStateMachineHelpers_nleref, "__stateMachine" , None , None , [vara; varb], ([[varaTy]], varbTy)) // inaccurate type but it doesn't matter for linking + let v_cgh__resumableEntry_info = makeIntrinsicValRef(fslib_MFStateMachineHelpers_nleref, "__resumableEntry" , None , None , [vara], ([[v_int_ty --> varaTy]; [v_unit_ty --> varaTy]], varaTy)) + let v_seq_to_array_info = makeIntrinsicValRef(fslib_MFSeqModule_nleref, "toArray" , None , Some "ToArray", [varb], ([[mkSeqTy varbTy]], mkArrayType 1 varbTy)) let v_seq_to_list_info = makeIntrinsicValRef(fslib_MFSeqModule_nleref, "toList" , None , Some "ToList" , [varb], ([[mkSeqTy varbTy]], mkListTy varbTy)) let v_seq_map_info = makeIntrinsicValRef(fslib_MFSeqModule_nleref, "map" , None , Some "Map" , [vara;varb], ([[varaTy --> varbTy]; [mkSeqTy varaTy]], mkSeqTy varbTy)) let v_seq_singleton_info = makeIntrinsicValRef(fslib_MFSeqModule_nleref, "singleton" , None , Some "Singleton" , [vara], ([[varaTy]], mkSeqTy varaTy)) @@ -1003,6 +1008,10 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member val ListCollector_tcr = mk_MFCompilerServices_tcref fslibCcu "ListCollector`1" member val ArrayCollector_tcr = mk_MFCompilerServices_tcref fslibCcu "ArrayCollector`1" member g.mk_GeneratedSequenceBase_ty seqElemTy = TType_app(g.seq_base_tcr,[seqElemTy]) + member val ResumableStateMachine_tcr = mk_MFCompilerServices_tcref fslibCcu "ResumableStateMachine`1" + member g.mk_ResumableStateMachine_ty dataTy = TType_app(g.ResumableStateMachine_tcr,[dataTy]) + member val IResumableStateMachine_tcr = mk_MFCompilerServices_tcref fslibCcu "IResumableStateMachine`1" + member g.mk_IResumableStateMachine_ty dataTy = TType_app(g.IResumableStateMachine_tcr,[dataTy]) member g.mk_ListCollector_ty seqElemTy = TType_app(g.ListCollector_tcr,[seqElemTy]) member g.mk_ArrayCollector_ty seqElemTy = TType_app(g.ArrayCollector_tcr,[seqElemTy]) member val byrefkind_In_tcr = mkNonLocalTyconRef fslib_MFByRefKinds_nleref "In" @@ -1011,6 +1020,8 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member val measureproduct_tcr = mk_MFCompilerServices_tcref fslibCcu "MeasureProduct`2" member val measureinverse_tcr = mk_MFCompilerServices_tcref fslibCcu "MeasureInverse`1" member val measureone_tcr = mk_MFCompilerServices_tcref fslibCcu "MeasureOne" + member val ResumableCode_tcr = mk_MFCompilerServices_tcref fslibCcu "ResumableCode`2" + member _.il_arr_tcr_map = v_il_arr_tcr_map member _.ref_tuple1_tcr = v_ref_tuple1_tcr member _.ref_tuple2_tcr = v_ref_tuple2_tcr @@ -1105,7 +1116,8 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d tryMkSysNonGenericTy ["System"; "Runtime"; "ExceptionServices"] "ExceptionDispatchInfo" member _.system_Reflection_MethodInfo_ty = v_system_Reflection_MethodInfo_ty - + member _.mk_IAsyncStateMachine_ty = mkSysNonGenericTy sysCompilerServices "IAsyncStateMachine" + member val system_Array_tcref = v_Array_tcref member val system_Object_tcref = findSysTyconRef sys "Object" member val system_Value_tcref = findSysTyconRef sys "ValueType" @@ -1234,6 +1246,7 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member val attrib_CompilationArgumentCountsAttribute = mk_MFCore_attrib "CompilationArgumentCountsAttribute" member val attrib_CompilationMappingAttribute = mk_MFCore_attrib "CompilationMappingAttribute" member val attrib_CLIEventAttribute = mk_MFCore_attrib "CLIEventAttribute" + member val attrib_InlineIfLambdaAttribute = mk_MFCore_attrib "InlineIfLambdaAttribute" member val attrib_CLIMutableAttribute = mk_MFCore_attrib "CLIMutableAttribute" member val attrib_AllowNullLiteralAttribute = mk_MFCore_attrib "AllowNullLiteralAttribute" member val attrib_NoEqualityAttribute = mk_MFCore_attrib "NoEqualityAttribute" @@ -1492,6 +1505,11 @@ type public TcGlobals(compilingFslib: bool, ilg:ILGlobals, fslibCcu: CcuThunk, d member _.quote_to_linq_lambda_info = v_quote_to_linq_lambda_info + member val cgh__stateMachine_vref = ValRefForIntrinsic v_cgh__stateMachine_info + member val cgh__useResumableCode_vref = ValRefForIntrinsic v_cgh__useResumableCode_info + member val cgh__resumeAt_vref = ValRefForIntrinsic v_cgh__resumeAt_info + member val cgh__resumableEntry_vref = ValRefForIntrinsic v_cgh__resumableEntry_info + member val generic_hash_withc_tuple2_vref = ValRefForIntrinsic v_generic_hash_withc_tuple2_info member val generic_hash_withc_tuple3_vref = ValRefForIntrinsic v_generic_hash_withc_tuple3_info member val generic_hash_withc_tuple4_vref = ValRefForIntrinsic v_generic_hash_withc_tuple4_info diff --git a/src/fsharp/TypedTree.fs b/src/fsharp/TypedTree.fs index 3798883baee..f6cc7a0eb12 100644 --- a/src/fsharp/TypedTree.fs +++ b/src/fsharp/TypedTree.fs @@ -39,9 +39,6 @@ type StampMap<'T> = Map [] type ValInline = - /// Indicates the value must always be inlined and no .NET IL code is generated for the value/function - | PseudoVal - /// Indicates the value is inlined but the .NET IL code for the function still exists, e.g. to satisfy interfaces on objects, but that it is also always inlined | Always @@ -54,7 +51,7 @@ type ValInline = /// Returns true if the implementation of a value must always be inlined member x.MustInline = match x with - | ValInline.PseudoVal | ValInline.Always -> true + | ValInline.Always -> true | ValInline.Optional | ValInline.Never -> false /// A flag associated with values that indicates whether the recursive scope of the value is currently being processed, and @@ -110,7 +107,6 @@ type ValFlags(flags: int64) = (if isCompGen then 0b00000000000000001000L else 0b000000000000000000000L) ||| (match inlineInfo with - | ValInline.PseudoVal -> 0b00000000000000000000L | ValInline.Always -> 0b00000000000000010000L | ValInline.Optional -> 0b00000000000000100000L | ValInline.Never -> 0b00000000000000110000L) ||| @@ -142,7 +138,7 @@ type ValFlags(flags: int64) = (match isGeneratedEventVal with | false -> 0b00000000000000000000L - | true -> 0b00100000000000000000L) + | true -> 0b00100000000000000000L) ValFlags flags @@ -167,7 +163,7 @@ type ValFlags(flags: int64) = member x.InlineInfo = match (flags &&& 0b00000000000000110000L) with - | 0b00000000000000000000L -> ValInline.PseudoVal + | 0b00000000000000000000L | 0b00000000000000010000L -> ValInline.Always | 0b00000000000000100000L -> ValInline.Optional | 0b00000000000000110000L -> ValInline.Never @@ -204,11 +200,11 @@ type ValFlags(flags: int64) = member x.WithRecursiveValInfo recValInfo = let flags = - (flags &&& ~~~0b00000001100000000000L) ||| + (flags &&& ~~~0b00000001100000000000L) ||| (match recValInfo with - | ValNotInRecScope -> 0b00000000000000000000L - | ValInRecScope true -> 0b00000000100000000000L - | ValInRecScope false -> 0b00000001000000000000L) + | ValNotInRecScope -> 0b00000000000000000000L + | ValInRecScope true -> 0b00000000100000000000L + | ValInRecScope false -> 0b00000001000000000000L) ValFlags flags member x.MakesNoCriticalTailcalls = (flags &&& 0b00000010000000000000L) <> 0L @@ -235,13 +231,17 @@ type ValFlags(flags: int64) = member x.WithIgnoresByrefScope = ValFlags(flags ||| 0b10000000000000000000L) + member x.InlineIfLambda = (flags &&& 0b100000000000000000000L) <> 0L + + member x.WithInlineIfLambda = ValFlags(flags ||| 0b100000000000000000000L) + /// Get the flags as included in the F# binary metadata member x.PickledBits = // Clear the RecursiveValInfo, only used during inference and irrelevant across assembly boundaries // Clear the IsCompiledAsStaticPropertyWithoutField, only used to determine whether to use a true field for a value, and to eliminate the optimization info for observable bindings // Clear the HasBeenReferenced, only used to report "unreferenced variable" warnings and to help collect 'it' values in FSI.EXE // Clear the IsGeneratedEventVal, since there's no use in propagating specialname information for generated add/remove event vals - (flags &&& ~~~0b10011001100000000000L) + (flags &&& ~~~0b010011001100000000000L) /// Represents the kind of a type parameter [] @@ -2707,6 +2707,9 @@ type Val = /// Get the inline declaration on the value member x.InlineInfo = x.val_flags.InlineInfo + /// Get the inline declaration on a parameter or other non-function-declaration value, used for optimization + member x.InlineIfLambda = x.val_flags.InlineIfLambda + /// Indicates whether the inline declaration for the value indicate that the value must be inlined? member x.MustInline = x.InlineInfo.MustInline @@ -2916,6 +2919,8 @@ type Val = member x.SetIgnoresByrefScope() = x.val_flags <- x.val_flags.WithIgnoresByrefScope + member x.SetInlineIfLambda() = x.val_flags <- x.val_flags.WithInlineIfLambda + member x.SetValReprInfo info = match x.val_opt_data with | Some optData -> optData.val_repr_info <- info @@ -3777,6 +3782,9 @@ type ValRef = /// Get the inline declaration on the value member x.InlineInfo = x.Deref.InlineInfo + /// Get the inline declaration on a parameter or other non-function-declaration value, used for optimization + member x.InlineIfLambda = x.Deref.InlineIfLambda + /// Indicates whether the inline declaration for the value indicate that the value must be inlined? member x.MustInline = x.Deref.MustInline @@ -4306,22 +4314,38 @@ type DecisionTreeTest = override x.ToString() = sprintf "%+A" x /// A target of a decision tree. Can be thought of as a little function, though is compiled as a local block. +/// -- boundVals - The values bound at the target, matching the valuesin the TDSuccess +/// -- targetExpr - The expression to evaluate if we branch to the target +/// -- debugPoint - The debug point for the target +/// -- isStateVarFlags - Indicates which, if any, of the values are repesents as state machine variables [] type DecisionTreeTarget = - | TTarget of Val list * Expr * DebugPointForTarget + | TTarget of + boundVals: Val list * + targetExpr: Expr * + debugPoint: DebugPointForTarget * + isStateVarFlags: bool list option [] member x.DebugText = x.ToString() + member x.TargetExpression = (let (TTarget(_, expr, _, _)) = x in expr) + override x.ToString() = sprintf "DecisionTreeTarget(...)" /// A collection of simultaneous bindings type Bindings = Binding list /// A binding of a variable to an expression, as in a `let` binding or similar +/// -- val: The value being bound +/// -- expr: The expression to execute to get the value +/// -- debugPoint: The debug point for the binding [] type Binding = - | TBind of var: Val * expr: Expr * debugPoint: DebugPointAtBinding + | TBind of + var: Val * + expr: Expr * + debugPoint: DebugPointAtBinding /// The value being bound member x.Var = (let (TBind(v, _, _)) = x in v) @@ -4341,7 +4365,11 @@ type Binding = /// integer indicates which choice in the target set is being selected by this item. [] type ActivePatternElemRef = - | APElemRef of activePatternInfo: ActivePatternInfo * activePatternVal: ValRef * caseIndex: int * isStructRetTy: bool + | APElemRef of + activePatternInfo: ActivePatternInfo * + activePatternVal: ValRef * + caseIndex: int * + isStructRetTy: bool /// Get the full information about the active pattern being referred to member x.ActivePatternInfo = (let (APElemRef(info, _, _, _)) = x in info) @@ -4365,7 +4393,10 @@ type ActivePatternElemRef = [] type ValReprInfo = /// ValReprInfo (typars, args, result) - | ValReprInfo of typars: TyparReprInfo list * args: ArgReprInfo list list * result: ArgReprInfo + | ValReprInfo of + typars: TyparReprInfo list * + args: ArgReprInfo list list * + result: ArgReprInfo /// Get the extra information about the arguments for the value member x.ArgInfos = (let (ValReprInfo(_, args, _)) = x in args) @@ -4748,7 +4779,7 @@ type TOp = [] member x.DebugText = x.ToString() - + override op.ToString() = match op with | UnionCase ucref -> "UnionCase(" + ucref.CaseName + ")" diff --git a/src/fsharp/TypedTreeOps.fs b/src/fsharp/TypedTreeOps.fs index 9fd50c3f059..c90b5175425 100644 --- a/src/fsharp/TypedTreeOps.fs +++ b/src/fsharp/TypedTreeOps.fs @@ -1204,7 +1204,7 @@ type MatchBuilder(spBind, inpRange: range) = targets.Add tg n - member x.AddResultTarget(e, spTarget) = TDSuccess([], x.AddTarget(TTarget([], e, spTarget))) + member x.AddResultTarget(e, spTarget) = TDSuccess([], x.AddTarget(TTarget([], e, spTarget, None))) member x.CloseTargets() = targets |> ResizeArray.toList @@ -1786,6 +1786,8 @@ let isInterfaceTy g ty = | ILTypeMetadata (TILObjectReprData(_, _, td)) -> td.IsInterface | FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata -> isFSharpInterfaceTy g ty +let isFSharpDelegateTy g ty = isDelegateTy g ty && isFSharpObjModelTy g ty + let isClassTy g ty = match metadataOfTy g ty with #if !NO_EXTENSIONTYPING @@ -3067,6 +3069,7 @@ let IsMatchingFSharpAttributeOpt g attrOpt (Attrib(tcref2, _, _, _, _, _, _)) = let (|ExtractAttribNamedArg|_|) nm args = args |> List.tryPick (function (AttribNamedArg(nm2, _, _, v)) when nm = nm2 -> Some v | _ -> None) +let (|StringExpr|_|) = function Expr.Const (Const.String n, _, _) -> Some n | _ -> None let (|AttribInt32Arg|_|) = function AttribExpr(_, Expr.Const (Const.Int32 n, _, _)) -> Some n | _ -> None let (|AttribInt16Arg|_|) = function AttribExpr(_, Expr.Const (Const.Int16 n, _, _)) -> Some n | _ -> None let (|AttribBoolArg|_|) = function AttribExpr(_, Expr.Const (Const.Bool n, _, _)) -> Some n | _ -> None @@ -4108,7 +4111,7 @@ module DebugPrint = | (DecisionTreeTest.ActivePatternCase (exp, _, _, _, _, _)) -> wordL(tagText "query") ^^ exprL g exp | (DecisionTreeTest.Error _) -> wordL (tagText "error recovery") - and targetL g i (TTarget (argvs, body, _)) = + and targetL g i (TTarget (argvs, body, _, _)) = leftL(tagText "T") ^^ intL i ^^ tupleL (flatValsL argvs) ^^ rightL(tagText ":") --- exprL g body and flatValsL vs = vs |> List.map valL @@ -4479,11 +4482,11 @@ let freeTyvarsAllPublic tyvars = let (|LinearMatchExpr|_|) expr = match expr with - | Expr.Match (sp, m, dtree, [|tg1;(TTarget([], e2, sp2))|], m2, ty) -> Some(sp, m, dtree, tg1, e2, sp2, m2, ty) + | Expr.Match (sp, m, dtree, [|tg1;(TTarget([], e2, sp2, _))|], m2, ty) -> Some(sp, m, dtree, tg1, e2, sp2, m2, ty) | _ -> None let rebuildLinearMatchExpr (sp, m, dtree, tg1, e2, sp2, m2, ty) = - primMkMatch (sp, m, dtree, [|tg1;(TTarget([], e2, sp2))|], m2, ty) + primMkMatch (sp, m, dtree, [|tg1;(TTarget([], e2, sp2, None))|], m2, ty) /// Detect a subset of 'Expr.Op' expressions we process in a linear way (i.e. using tailcalls, rather than /// unbounded stack). Only covers Cons(args,Cons(args,Cons(args,Cons(args,...._)))). @@ -4844,8 +4847,10 @@ and accFreeInOp opts op acc = and accFreeInTargets opts targets acc = Array.foldBack (accFreeInTarget opts) targets acc -and accFreeInTarget opts (TTarget(vs, expr, _)) acc = - List.foldBack (boundLocalVal opts) vs (accFreeInExpr opts expr acc) +and accFreeInTarget opts (TTarget(vs, expr, _, flags)) acc = + match flags with + | None -> List.foldBack (boundLocalVal opts) vs (accFreeInExpr opts expr acc) + | Some xs -> List.foldBack2 (fun v isStateVar acc -> if isStateVar then acc else boundLocalVal opts v acc) vs xs (accFreeInExpr opts expr acc) and accFreeInFlatExprs opts (exprs: Exprs) acc = List.foldBack (accFreeInExpr opts) exprs acc @@ -5214,12 +5219,7 @@ and remapExpr (g: TcGlobals) (compgen: ValCopyFlag) (tmenv: Remap) expr = // Binding constructs - see also dtrees below | Expr.Lambda (_, ctorThisValOpt, baseValOpt, vs, b, m, rty) -> - let ctorThisValOpt, tmenv = Option.mapFold (copyAndRemapAndBindVal g compgen) tmenv ctorThisValOpt - let baseValOpt, tmenv = Option.mapFold (copyAndRemapAndBindVal g compgen) tmenv baseValOpt - let vs, tmenv = copyAndRemapAndBindVals g compgen tmenv vs - let b = remapExpr g compgen tmenv b - let rty = remapType tmenv rty - Expr.Lambda (newUnique(), ctorThisValOpt, baseValOpt, vs, b, m, rty) + remapLambaExpr g compgen tmenv (ctorThisValOpt, baseValOpt, vs, b, m, rty) | Expr.TyLambda (_, tps, b, m, rty) -> let tps', tmenvinner = tmenvCopyRemapAndBindTypars (remapAttribs g tmenv) tmenv tps @@ -5245,14 +5245,7 @@ and remapExpr (g: TcGlobals) (compgen: ValCopyFlag) (tmenv: Remap) expr = else Expr.Val (vr', vf', m) | Expr.Quote (a, dataCell, isFromQueryExpression, m, ty) -> - let doData (typeDefs, argTypes, argExprs, res) = (typeDefs, remapTypesAux tmenv argTypes, remapExprs g compgen tmenv argExprs, res) - let data' = - match dataCell.Value with - | None -> None - | Some (data1, data2) -> Some (doData data1, doData data2) - // fix value of compgen for both original expression and pickled AST - let compgen = fixValCopyFlagForQuotations compgen - Expr.Quote (remapExpr g compgen tmenv a, ref data', isFromQueryExpression, m, remapType tmenv ty) + remapQuoteExpr g compgen tmenv (a, dataCell, isFromQueryExpression, m, ty) | Expr.Obj (_, ty, basev, basecall, overrides, iimpls, m) -> let basev', tmenvinner = Option.mapFold (copyAndRemapAndBindVal g compgen) tmenv basev @@ -5285,19 +5278,10 @@ and remapExpr (g: TcGlobals) (compgen: ValCopyFlag) (tmenv: Remap) expr = mkCompGenLet m tmp (mkUnionCaseFieldGetProvenViaExprAddr (arg, uref, tinst, cidx, m)) (mkValAddr m readonly (mkLocalValRef tmp)) | Expr.Op (op, tinst, args, m) -> - let op' = remapOp tmenv op - let tinst' = remapTypes tmenv tinst - let args' = remapExprs g compgen tmenv args - if op === op' && tinst === tinst' && args === args' then expr - else Expr.Op (op', tinst', args', m) + remapOpExpr g compgen tmenv (op, tinst, args, m) expr | Expr.App (e1, e1ty, tyargs, args, m) -> - let e1' = remapExpr g compgen tmenv e1 - let e1ty' = remapPossibleForallTy g tmenv e1ty - let tyargs' = remapTypes tmenv tyargs - let args' = remapExprs g compgen tmenv args - if e1 === e1' && e1ty === e1ty' && tyargs === tyargs' && args === args' then expr - else Expr.App (e1', e1ty', tyargs', args', m) + remapAppExpr g compgen tmenv (e1, e1ty, tyargs, args, m) expr | Expr.Link eref -> remapExpr g compgen tmenv !eref @@ -5314,9 +5298,42 @@ and remapExpr (g: TcGlobals) (compgen: ValCopyFlag) (tmenv: Remap) expr = let traitInfoR = remapTraitInfo tmenv traitInfo Expr.WitnessArg (traitInfoR, m) -and remapTarget g compgen tmenv (TTarget(vs, e, spTarget)) = +and remapLambaExpr (g: TcGlobals) (compgen: ValCopyFlag) (tmenv: Remap) (ctorThisValOpt, baseValOpt, vs, b, m, rty) = + let ctorThisValOpt, tmenv = Option.mapFold (copyAndRemapAndBindVal g compgen) tmenv ctorThisValOpt + let baseValOpt, tmenv = Option.mapFold (copyAndRemapAndBindVal g compgen) tmenv baseValOpt + let vs, tmenv = copyAndRemapAndBindVals g compgen tmenv vs + let b = remapExpr g compgen tmenv b + let rty = remapType tmenv rty + Expr.Lambda (newUnique(), ctorThisValOpt, baseValOpt, vs, b, m, rty) + +and remapQuoteExpr (g: TcGlobals) (compgen: ValCopyFlag) (tmenv: Remap) (a, dataCell, isFromQueryExpression, m, ty) = + let doData (typeDefs, argTypes, argExprs, res) = (typeDefs, remapTypesAux tmenv argTypes, remapExprs g compgen tmenv argExprs, res) + let data' = + match dataCell.Value with + | None -> None + | Some (data1, data2) -> Some (doData data1, doData data2) + // fix value of compgen for both original expression and pickled AST + let compgen = fixValCopyFlagForQuotations compgen + Expr.Quote (remapExpr g compgen tmenv a, ref data', isFromQueryExpression, m, remapType tmenv ty) + +and remapOpExpr (g: TcGlobals) (compgen: ValCopyFlag) (tmenv: Remap) (op, tinst, args, m) origExpr = + let op' = remapOp tmenv op + let tinst' = remapTypes tmenv tinst + let args' = remapExprs g compgen tmenv args + if op === op' && tinst === tinst' && args === args' then origExpr + else Expr.Op (op', tinst', args', m) + +and remapAppExpr (g: TcGlobals) (compgen: ValCopyFlag) (tmenv: Remap) (e1, e1ty, tyargs, args, m) origExpr = + let e1' = remapExpr g compgen tmenv e1 + let e1ty' = remapPossibleForallTy g tmenv e1ty + let tyargs' = remapTypes tmenv tyargs + let args' = remapExprs g compgen tmenv args + if e1 === e1' && e1ty === e1ty' && tyargs === tyargs' && args === args' then origExpr + else Expr.App (e1', e1ty', tyargs', args', m) + +and remapTarget g compgen tmenv (TTarget(vs, e, spTarget, flags)) = let vs', tmenvinner = copyAndRemapAndBindVals g compgen tmenv vs - TTarget(vs', remapExpr g compgen tmenvinner e, spTarget) + TTarget(vs', remapExpr g compgen tmenvinner e, spTarget, flags) and remapLinearExpr g compgen tmenv expr contf = @@ -5727,7 +5744,7 @@ let rec remarkExpr m x = Expr.Let (remarkBind m bind, remarkExpr m e, m, fvs) | Expr.Match (_, _, pt, targets, _, ty) -> - let targetsR = targets |> Array.map (fun (TTarget(vs, e, _)) -> TTarget(vs, remarkExpr m e, DebugPointForTarget.No)) + let targetsR = targets |> Array.map (fun (TTarget(vs, e, _, flags)) -> TTarget(vs, remarkExpr m e, DebugPointForTarget.No, flags)) primMkMatch (DebugPointAtBinding.NoneAtInvisible, m, remarkDecisionTree m pt, targetsR, m, ty) | Expr.Val (x, valUseFlags, _) -> @@ -5742,10 +5759,38 @@ let rec remarkExpr m x = List.map (remarkInterfaceImpl m) iimpls, m) | Expr.Op (op, tinst, args, _) -> + + // If this is ultimately being inlined as the implementation + // of a 'while'/'for' etc in a computation expression then lay down a + // debug point let op = match op with - | TOp.TryFinally (_, _) -> TOp.TryFinally (DebugPointAtTry.No, DebugPointAtFinally.No) - | TOp.TryWith (_, _) -> TOp.TryWith (DebugPointAtTry.No, DebugPointAtWith.No) + | TOp.For (spFor, style) -> + let spFor2 = + match m.DebugPointKind with + | RangeDebugPointKind.For -> DebugPointAtFor.Yes m + | _ -> spFor + TOp.For(spFor2, style) + | TOp.While (spWhile, marker) -> + let spWhile2 = + match m.DebugPointKind with + | RangeDebugPointKind.While -> DebugPointAtWhile.Yes m + | _ -> spWhile + TOp.While(spWhile2, marker) + | TOp.TryFinally (spTry, _) -> + let spTry2 = + match m.DebugPointKind with + | RangeDebugPointKind.Try -> DebugPointAtTry.Yes m + | _ -> spTry + // The debug point for the 'finally' is not yet recoverable + TOp.TryFinally (spTry2, DebugPointAtFinally.No) + | TOp.TryWith (spTry, _) -> + let spTry2 = + match m.DebugPointKind with + | RangeDebugPointKind.Try -> DebugPointAtTry.Yes m + | _ -> spTry + // The debug point for the 'with' is not yet recoverable + TOp.TryWith (spTry2, DebugPointAtWith.No) | _ -> op Expr.Op (op, tinst, remarkExprs m args, m) @@ -5757,8 +5802,31 @@ let rec remarkExpr m x = | Expr.App (e1, e1ty, tyargs, args, _) -> Expr.App (remarkExpr m e1, e1ty, tyargs, remarkExprs m args, m) - | Expr.Sequential (e1, e2, dir, _, _) -> - Expr.Sequential (remarkExpr m e1, remarkExpr m e2, dir, DebugPointAtSequential.StmtOnly, m) + | Expr.Sequential (e1, e2, dir, sp, _) -> + let e1R = remarkExpr m e1 + let e2R = remarkExpr m e2 + + // This is to suppress false sequence points when inlining 'ResumableCode.TryWith' + // It is adhoc and may need to be improved if the library implementation changes + // + // For this specific code: + // + // __stack_caught <- true + // __stack_savedExn <- ... + // + // we suppress the sequence points on both the sequentials. + // + // Normally inlining associates all of the inlined code with the expression range of the overall construct, + // which for computation expression calls TryFinally and TryWith is the 'try' keyword. + // However this is broken when inlining sophisticated control flow as the 'with' and 'finally' + // parts of the code get the 'try' keyword as their sequence point range. + let sp = + match sp, e2R with + | DebugPointAtSequential.SuppressBoth, _ -> DebugPointAtSequential.SuppressBoth + | _, Expr.Op(TOp.LValueOp (LSet _, v), _, _, _) when v.DisplayName = "__stack_savedExn" -> DebugPointAtSequential.SuppressBoth + | _ -> DebugPointAtSequential.SuppressStmt + + Expr.Sequential (e1R, e2R, dir, sp, m) | Expr.StaticOptimization (eqns, e2, e3, _) -> Expr.StaticOptimization (eqns, remarkExpr m e2, remarkExpr m e3, m) @@ -6124,7 +6192,7 @@ let foldLinearBindingTargetsOfMatch tree (targets: _[]) = /// rebuild the targets, replacing linear targets by ones that include all the 'let' bindings from the source let targets' = - targets |> Array.mapi (fun i (TTarget(vs, exprTarget, spTarget) as tg) -> + targets |> Array.mapi (fun i (TTarget(vs, exprTarget, spTarget, _) as tg) -> if isLinearTgtIdx i then let (binds, es) = getLinearTgtIdx i // The value bindings are moved to become part of the target. @@ -6132,7 +6200,7 @@ let foldLinearBindingTargetsOfMatch tree (targets: _[]) = let mTarget = exprTarget.Range let es = es |> List.map (remarkExpr mTarget) // These are non-sticky - any sequence point for 'exprTarget' goes on 'exprTarget' _after_ the bindings have been evaluated - TTarget(List.empty, mkLetsBind mTarget binds (mkInvisibleLetsFromBindings mTarget vs es exprTarget), spTarget) + TTarget(List.empty, mkLetsBind mTarget binds (mkInvisibleLetsFromBindings mTarget vs es exprTarget), spTarget, None) else tg ) tree', targets' @@ -6143,7 +6211,7 @@ let rec simplifyTrivialMatch spBind exprm matchm ty tree (targets : _[]) = | TDSuccess(es, n) -> if n >= targets.Length then failwith "simplifyTrivialMatch: target out of range" // REVIEW: should we use _spTarget here? - let (TTarget(vs, rhs, _spTarget)) = targets.[n] + let (TTarget(vs, rhs, _spTarget, _)) = targets.[n] if vs.Length <> es.Length then failwith ("simplifyTrivialMatch: invalid argument, n = " + string n + ", List.length targets = " + string targets.Length) // These are non-sticky - any sequence point for 'rhs' goes on 'rhs' _after_ the bindings have been made mkInvisibleLetsFromBindings rhs.Range vs es rhs @@ -6667,7 +6735,7 @@ type ExprFolders<'State> (folders: ExprFolder<'State>) = match folders.targetIntercept exprFClosure z x with | Some z -> z // intercepted | None -> // structurally recurse - let (TTarget (_, body, _)) = x + let (TTarget (_, body, _, _)) = x exprF z body and tmethodF z x = @@ -6776,7 +6844,11 @@ let mkRefCellContentsRef (g: TcGlobals) = mkRecdFieldRef g.refcell_tcr_canon "co let mkSequential spSeq m e1 e2 = Expr.Sequential (e1, e2, NormalSeq, spSeq, m) -let mkCompGenSequential m e1 e2 = mkSequential DebugPointAtSequential.StmtOnly m e1 e2 +let mkCompGenSequential m stmt expr = mkSequential DebugPointAtSequential.SuppressStmt m stmt expr + +let mkThenDoSequential spSeq m expr stmt = Expr.Sequential (expr, stmt, ThenDoSeq, spSeq, m) + +let mkCompGenThenDoSequential m expr stmt = mkThenDoSequential DebugPointAtSequential.SuppressStmt m expr stmt let rec mkSequentials spSeq g m es = match es with @@ -7575,6 +7647,33 @@ let rec MakeApplicationAndBetaReduceAux g (f, fty, tyargsl: TType list list, arg let MakeApplicationAndBetaReduce g (f, fty, tyargsl, argl, m) = MakeApplicationAndBetaReduceAux g (f, fty, tyargsl, argl, m) +let (|NewDelegateExpr|_|) g expr = + match expr with + | Expr.Obj (lambdaId, ty, a, b, [TObjExprMethod(c, d, e, tmvs, body, f)], [], m) when isDelegateTy g ty -> + Some (lambdaId, tmvs, body, m, (fun bodyR -> Expr.Obj (lambdaId, ty, a, b, [TObjExprMethod(c, d, e, tmvs, bodyR, f)], [], m))) + | _ -> None + +let (|DelegateInvokeExpr|_|) g expr = + match expr with + | Expr.App ((Expr.Val (invokeRef, _, _)) as iref, fty, tyargs, (f :: args), m) + when invokeRef.LogicalName = "Invoke" && isFSharpDelegateTy g (tyOfExpr g f) -> + Some(iref, fty, tyargs, f, args, m) + | _ -> None + +let rec MakeFSharpDelegateInvokeAndTryBetaReduce g (invokeRef, f, fty, tyargs, argsl: Expr list, m) = + match f with + | Expr.Let (bind, body, mlet, _) -> + mkLetBind mlet bind (MakeFSharpDelegateInvokeAndTryBetaReduce g (invokeRef, body, fty, tyargs, argsl, m)) + | _ -> + match f with + | NewDelegateExpr g (_, argvsl, body, m, _) when argvsl.Length = argsl.Length -> + let pairs, body = List.mapFoldBack (MultiLambdaToTupledLambdaIfNeeded g) (List.zip argvsl argsl) body + let argvs2, args2 = List.unzip (List.concat pairs) + mkLetsBind m (mkCompGenBinds argvs2 args2) body + | _ -> + // Remake the delegate invoke + Expr.App (invokeRef, fty, tyargs, (f :: argsl), m) + //--------------------------------------------------------------------------- // Adjust for expected usage // Convert a use of a value to saturate to the given arity. @@ -7973,10 +8072,10 @@ let LinearizeTopMatchAux g parent (spBind, m, tree, targets, m2, ty) = | [] -> failwith "itemsProj: no items?" | [_] -> x (* no projection needed *) | tys -> Expr.Op (TOp.TupleFieldGet (tupInfoRef, i), tys, [x], m) - let isThrowingTarget = function TTarget(_, x, _) -> isThrow x + let isThrowingTarget = function TTarget(_, x, _, _) -> isThrow x if 1 + List.count isThrowingTarget targetsL = targetsL.Length then // Have failing targets and ONE successful one, so linearize - let (TTarget (vs, rhs, spTarget)) = List.find (isThrowingTarget >> not) targetsL + let (TTarget (vs, rhs, spTarget, _)) = List.find (isThrowingTarget >> not) targetsL let fvs = vs |> List.map (fun v -> fst(mkLocal v.Range v.LogicalName v.Type)) (* fresh *) let vtys = vs |> List.map (fun v -> v.Type) let tmpTy = mkRefTupledVarsTy g vs @@ -7984,12 +8083,12 @@ let LinearizeTopMatchAux g parent (spBind, m, tree, targets, m2, ty) = AdjustValToTopVal tmp parent ValReprInfo.emptyValData - let newTg = TTarget (fvs, mkRefTupledVars g m fvs, spTarget) - let fixup (TTarget (tvs, tx, spTarget)) = + let newTg = TTarget (fvs, mkRefTupledVars g m fvs, spTarget, None) + let fixup (TTarget (tvs, tx, spTarget, flags)) = match destThrow tx with | Some (m, _, e) -> let tx = mkThrow m tmpTy e - TTarget(tvs, tx, spTarget) (* Throwing targets, recast it's "return type" *) + TTarget(tvs, tx, spTarget, flags) (* Throwing targets, recast it's "return type" *) | None -> newTg (* Non-throwing target, replaced [new/old] *) let targets = Array.map fixup targets @@ -8356,7 +8455,7 @@ let mkIsInstConditional g m tgty vinpe v e2 e3 = else let mbuilder = new MatchBuilder(DebugPointAtBinding.NoneAtInvisible, m) - let tg2 = TDSuccess([mkCallUnbox g m tgty vinpe], mbuilder.AddTarget(TTarget([v], e2, DebugPointForTarget.No))) + let tg2 = TDSuccess([mkCallUnbox g m tgty vinpe], mbuilder.AddTarget(TTarget([v], e2, DebugPointForTarget.No, None))) let tg3 = mbuilder.AddResultTarget(e3, DebugPointForTarget.No) let dtree = TDSwitch(vinpe, [TCase(DecisionTreeTest.IsInst(tyOfExpr g vinpe, tgty), tg2)], Some tg3, m) let expr = mbuilder.Close(dtree, m, tyOfExpr g e2) @@ -8708,8 +8807,8 @@ and RewriteDecisionTree env x = let body = RewriteDecisionTree env body TDBind (bind', body) -and rewriteTarget env (TTarget(vs, e, spTarget)) = - TTarget(vs, RewriteExpr env e, spTarget) +and rewriteTarget env (TTarget(vs, e, spTarget, flags)) = + TTarget(vs, RewriteExpr env e, spTarget, flags) and rewriteTargets env targets = List.map (rewriteTarget env) (Array.toList targets) @@ -8937,7 +9036,7 @@ let IsSimpleSyntacticConstantExpr g inputExpr = and checkDecisionTreeCase vrefs (TCase(discrim, dtree)) = (match discrim with DecisionTreeTest.Const _c -> true | _ -> false) && checkDecisionTree vrefs dtree - and checkDecisionTreeTarget vrefs (TTarget(vs, e, _)) = + and checkDecisionTreeTarget vrefs (TTarget(vs, e, _, _)) = let vrefs = ((vrefs, vs) ||> List.fold (fun s v -> s.Add v.Stamp)) checkExpr vrefs e @@ -9299,12 +9398,31 @@ let mkUnitDelayLambda (g: TcGlobals) m e = let uv, _ = mkCompGenLocal m "unitVar" g.unit_ty mkLambda m uv (e, tyOfExpr g e) + let (|ValApp|_|) g vref expr = match expr with - // use 'seq { ... }' as an indicator | Expr.App (Expr.Val (vref2, _, _), _f0ty, tyargs, args, m) when valRefEq g vref vref2 -> Some (tyargs, args, m) | _ -> None +let (|UseResumableStateMachinesExpr|_|) g expr = + match expr with + | ValApp g g.cgh__useResumableCode_vref (_, _, _m) -> Some () + | _ -> None + +/// Match +let (|IsThenElseExpr|_|) expr = + match expr with + | Expr.Match (_spBind, _exprm, TDSwitch(cond, [ TCase( DecisionTreeTest.Const (Const.Bool true), TDSuccess ([], 0) )], Some (TDSuccess ([], 1)), _), + [| TTarget([], thenExpr, _, _); TTarget([], elseExpr, _, _) |], _m, _ty) -> + Some (cond, thenExpr, elseExpr) + | _ -> None + +/// if __useResumableCode then ... else ... +let (|IfUseResumableStateMachinesExpr|_|) g expr = + match expr with + | IsThenElseExpr(UseResumableStateMachinesExpr g (), thenExpr, elseExpr) -> Some (thenExpr, elseExpr) + | _ -> None + /// Combine a list of ModuleOrNamespaceType's making up the description of a CCU. checking there are now /// duplicate modules etc. let CombineCcuContentFragments m l = @@ -9399,4 +9517,119 @@ let (|TryWithExpr|_|) expr = Some (spTry, spWith, resTy, bodyExpr, filterVar, filterExpr, handlerVar, handlerExpr, m) | _ -> None +let (|MatchTwoCasesExpr|_|) expr = + match expr with + | Expr.Match (spBind, exprm, TDSwitch(cond, [ TCase( DecisionTreeTest.UnionCase (ucref, a), TDSuccess ([], tg1) )], Some (TDSuccess ([], tg2)), b), tgs, m, ty) -> + + // How to rebuild this construct + let rebuild (cond, ucref, tg1, tg2, tgs) = + Expr.Match (spBind, exprm, TDSwitch(cond, [ TCase( DecisionTreeTest.UnionCase (ucref, a), TDSuccess ([], tg1) )], Some (TDSuccess ([], tg2)), b), tgs, m, ty) + + Some (cond, ucref, tg1, tg2, tgs, rebuild) + + | _ -> None + +/// match e with None -> ... | Some v -> ... or other variations of the same +let (|MatchOptionExpr|_|) expr = + match expr with + | MatchTwoCasesExpr(cond, ucref, tg1, tg2, tgs, rebuildTwoCases) -> + let tgNone, tgSome = if ucref.CaseName = "None" then tg1, tg2 else tg2, tg1 + match tgs.[tgNone], tgs.[tgSome] with + | TTarget([], noneBranchExpr, b1, b2), + TTarget([], Expr.Let(TBind(unionCaseVar, Expr.Op(TOp.UnionCaseProof a1, a2, a3, a4), a5), + Expr.Let(TBind(someVar, Expr.Op(TOp.UnionCaseFieldGet (a6a, a6b), a7, a8, a9), a10), someBranchExpr, a11, a12), a13, a14), a15, a16) + when unionCaseVar.LogicalName = "unionCase" -> + + // How to rebuild this construct + let rebuild (cond, noneBranchExpr, someVar, someBranchExpr) = + let tgs = Array.zeroCreate 2 + tgs.[tgNone] <- TTarget([], noneBranchExpr, b1, b2) + tgs.[tgSome] <- TTarget([], Expr.Let(TBind(unionCaseVar, Expr.Op(TOp.UnionCaseProof a1, a2, a3, a4), a5), + Expr.Let(TBind(someVar, Expr.Op(TOp.UnionCaseFieldGet (a6a, a6b), a7, a8, a9), a10), someBranchExpr, a11, a12), a13, a14), a15, a16) + rebuildTwoCases (cond, ucref, tg1, tg2, tgs) + + Some (cond, noneBranchExpr, someVar, someBranchExpr, rebuild) + | _ -> None + | _ -> None + +let (|ResumableEntryAppExpr|_|) g expr = + match expr with + | ValApp g g.cgh__resumableEntry_vref (_, _, _m) -> Some () + | _ -> None + +/// Match an (unoptimized) __resumableEntry expression +let (|ResumableEntryMatchExpr|_|) g expr = + match expr with + | Expr.Let(TBind(matchVar, matchExpr, sp1), MatchOptionExpr (Expr.Val(matchVar2, b, c), noneBranchExpr, someVar, someBranchExpr, rebuildMatch), d, e) -> + match matchExpr with + | ResumableEntryAppExpr g () -> + if valRefEq g (mkLocalValRef matchVar) matchVar2 then + + // How to rebuild this construct + let rebuild (noneBranchExpr, someBranchExpr) = + Expr.Let(TBind(matchVar, matchExpr, sp1), rebuildMatch (Expr.Val(matchVar2, b, c), noneBranchExpr, someVar, someBranchExpr), d, e) + + Some (noneBranchExpr, someVar, someBranchExpr, rebuild) + + else None + + | _ -> None + | _ -> None + +let (|PossiblyCompiledTypeOfExpr|_|) g expr = + match expr with + | TypeOfExpr g ty -> Some ty + | Expr.Op(TOp.ILCall (_, _, _, _, _, _, _, ilMethRef, _, _, _), [],[Expr.Op (TOp.ILAsm ([ I_ldtoken (ILToken.ILType _) ], _), [ty], _, _)], _) + when ilMethRef.DeclaringTypeRef.Name = "System.Type" && ilMethRef.Name = "GetTypeFromHandle" -> + Some ty + | _ -> None + +let (|StructStateMachineExpr|_|) g expr = + match expr with + | ValApp g g.cgh__stateMachine_vref ([dataTy; _resultTy], [moveNext; setStateMachine; afterCode], _m) -> + match moveNext, setStateMachine, afterCode with + | NewDelegateExpr g (_, [[moveNextThisVar]], moveNextBody, _, _), + NewDelegateExpr g (_, [[setStateMachineThisVar;setStateMachineStateVar]], setStateMachineBody, _, _), + NewDelegateExpr g (_, [[afterCodeThisVar]], afterCodeBody, _, _) -> + Some (dataTy, + (moveNextThisVar, moveNextBody), + (setStateMachineThisVar, setStateMachineStateVar, setStateMachineBody), + (afterCodeThisVar, afterCodeBody)) + | _ -> None + | _ -> None + +let (|ResumeAtExpr|_|) g expr = + match expr with + | ValApp g g.cgh__resumeAt_vref (_, [pcExpr], _m) -> Some pcExpr + | _ -> None + +// Detect sequencing constructs in state machine code +let (|SequentialResumableCode|_|) (g: TcGlobals) expr = + match expr with + + // e1; e2 + | Expr.Sequential(e1, e2, NormalSeq, sp, m) -> + Some (e1, e2, m, (fun e1 e2 -> Expr.Sequential(e1, e2, NormalSeq, sp, m))) + + // let __stack_step = e1 in e2 + | Expr.Let(bind, e2, m, _) when bind.Var.CompiledName(g.CompilerGlobalState).StartsWith(stackVarPrefix) -> + Some (bind.Expr, e2, m, (fun e1 e2 -> mkLet bind.DebugPoint m bind.Var e1 e2)) + + | _ -> None + let mkLabelled m l e = mkCompGenSequential m (Expr.Op (TOp.Label l, [], [], m)) e + +let isResumableCodeTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref, _) -> tyconRefEq g tcref g.ResumableCode_tcr | _ -> false) + +let rec isReturnsResumableCodeTy g ty = + if isFunTy g ty then isReturnsResumableCodeTy g (rangeOfFunTy g ty) + else isResumableCodeTy g ty + +let (|ResumableCodeInvoke|_|) g expr = + match expr with + // defn.Invoke x --> let arg = x in [defn][arg/x] + | Expr.App ((Expr.Val (invokeRef, _, _) as iref), a, b, (f :: args), m) + when invokeRef.LogicalName = "Invoke" && isReturnsResumableCodeTy g (tyOfExpr g f) -> + Some (iref, f, args, m, (fun (f2, args2) -> Expr.App ((iref, a, b, (f2 :: args2), m)))) + | _ -> None + diff --git a/src/fsharp/TypedTreeOps.fsi b/src/fsharp/TypedTreeOps.fsi index 8e3dc20b995..7120778d8a4 100755 --- a/src/fsharp/TypedTreeOps.fsi +++ b/src/fsharp/TypedTreeOps.fsi @@ -9,6 +9,7 @@ open Internal.Utilities.Collections open Internal.Utilities.Rational open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL.IL +open FSharp.Compiler.CompilerGlobalState open FSharp.Compiler.Syntax open FSharp.Compiler.Text open FSharp.Compiler.Xml @@ -1309,8 +1310,13 @@ val MultiLambdaToTupledLambda: TcGlobals -> Val list -> Expr -> Val * Expr val AdjustArityOfLambdaBody: TcGlobals -> int -> Val list -> Expr -> Val list * Expr /// Make an application expression, doing beta reduction by introducing let-bindings +/// if the function expression is a construction of a lambda val MakeApplicationAndBetaReduce: TcGlobals -> Expr * TType * TypeInst list * Exprs * range -> Expr +/// Make a delegate invoke expression for an F# delegate type, doing beta reduction by introducing let-bindings +/// if the delegate expression is a construction of a delegate. +val MakeFSharpDelegateInvokeAndTryBetaReduce: TcGlobals -> invokeRef: Expr * f: Expr * fty: TType * tyargs: TypeInst * argsl: Exprs * m: range -> Expr + /// Combine two static-resolution requirements on a type parameter val JoinTyparStaticReq: TyparStaticReq -> TyparStaticReq -> TyparStaticReq @@ -1542,6 +1548,9 @@ val isInterfaceTyconRef: TyconRef -> bool /// Determine if a type is a delegate type val isDelegateTy: TcGlobals -> TType -> bool +/// Determine if a type is a delegate type defined in F# +val isFSharpDelegateTy: TcGlobals -> TType -> bool + /// Determine if a type is an interface type val isInterfaceTy: TcGlobals -> TType -> bool @@ -1750,7 +1759,15 @@ val mkOptionDefaultValue: TcGlobals -> range -> TType -> Expr -> Expr -> Expr val mkSequential: DebugPointAtSequential -> range -> Expr -> Expr -> Expr -val mkCompGenSequential: range -> Expr -> Expr -> Expr +val mkThenDoSequential: DebugPointAtSequential -> range -> expr: Expr -> stmt: Expr -> Expr + +/// This is used for tacking on code _before_ the expression. The SuppressStmt +/// setting is used for debug points, suppressing the debug points for the statement if possible. +val mkCompGenSequential: range -> stmt: Expr -> expr: Expr -> Expr + +/// This is used for tacking on code _after_ the expression. The SuppressStmt +/// setting is used for debug points, suppressing the debug points for the statement if possible. +val mkCompGenThenDoSequential: range -> expr: Expr -> stmt: Expr -> Expr val mkSequentials: DebugPointAtSequential -> TcGlobals -> range -> Exprs -> Expr @@ -2145,6 +2162,7 @@ val TryFindInternalsVisibleToAttr: ILAttribute -> string option val IsMatchingSignatureDataVersionAttr: ILVersionInfo -> ILAttribute -> bool val mkCompilationMappingAttr: TcGlobals -> int -> ILAttribute + val mkCompilationMappingAttrWithSeqNum: TcGlobals -> int -> int -> ILAttribute @@ -2307,6 +2325,8 @@ type ExprRewritingEnv = PreInterceptBinding: ((Expr -> Expr) -> Binding -> Binding option) option IsUnderQuotations: bool } +val RewriteDecisionTree: ExprRewritingEnv -> DecisionTree -> DecisionTree + val RewriteExpr: ExprRewritingEnv -> Expr -> Expr val RewriteImplFile: ExprRewritingEnv -> TypedImplFile -> TypedImplFile @@ -2424,8 +2444,32 @@ val EmptyTraitWitnessInfoHashMap: TcGlobals -> TraitWitnessInfoHashMap<'T> /// Match expressions that are an application of a particular F# function value val (|ValApp|_|): TcGlobals -> ValRef -> Expr -> (TypeInst * Exprs * range) option +/// Match expressions that represent the creation of an instance of an F# delegate value +val (|NewDelegateExpr|_|): TcGlobals -> Expr -> (Unique * Val list list * Expr * range * (Expr -> Expr)) option + +/// Match a .Invoke on a delegate +val (|DelegateInvokeExpr|_|): TcGlobals -> Expr -> (Expr * TType * TypeInst * Expr * Exprs * range) option + +/// Match 'if __useResumableCode then ... else ...' expressions +val (|IfUseResumableStateMachinesExpr|_|) : TcGlobals -> Expr -> (Expr * Expr) option + val CombineCcuContentFragments: range -> ModuleOrNamespaceType list -> ModuleOrNamespaceType +/// Recognise a 'match __resumableEntry() with ...' expression +val (|ResumableEntryMatchExpr|_|): g: TcGlobals -> Expr -> (Expr * Val * Expr * (Expr * Expr -> Expr)) option + +/// Recognise a '__stateMachine' expression +val (|StructStateMachineExpr|_|): + g: TcGlobals -> + expr: Expr -> + (TType * (Val * Expr) * (Val * Val * Expr) * (Val * Expr)) option + +/// Recognise a sequential or binding construct in a resumable code +val (|SequentialResumableCode|_|): g: TcGlobals -> Expr -> (Expr * Expr * range * (Expr -> Expr -> Expr)) option + +/// Recognise a '__resumeAt' expression +val (|ResumeAtExpr|_|): g: TcGlobals -> Expr -> Expr option + /// Recognise a while expression val (|WhileExpr|_|): Expr -> (DebugPointAtWhile * SpecialWhileLoopMarker * Expr * Expr * range) option @@ -2441,6 +2485,12 @@ val (|TryFinallyExpr|_|): Expr -> (DebugPointAtTry * DebugPointAtFinally * TType /// Add a label to use as the target for a goto val mkLabelled: range -> ILCodeLabel -> Expr -> Expr +/// Any delegate type with ResumableCode attribute, or any function returning such a delegate type +val isResumableCodeTy: TcGlobals -> TType -> bool + +/// The delegate type ResumableCode, or any function returning this a delegate type +val isReturnsResumableCodeTy: TcGlobals -> TType -> bool + /// Shared helper for binding attributes val TryBindTyconRefAttribute: g:TcGlobals -> @@ -2451,3 +2501,9 @@ val TryBindTyconRefAttribute: f2:(Attrib -> 'a option) -> f3:(obj option list * (string * obj option) list -> 'a option) -> 'a option + +val (|ResumableCodeInvoke|_|): + g:TcGlobals -> + expr: Expr -> + (Expr * Expr * Expr list * range * (Expr * Expr list -> Expr)) option + \ No newline at end of file diff --git a/src/fsharp/TypedTreePickle.fs b/src/fsharp/TypedTreePickle.fs index 0ed89d9e8bc..8b5d3be9248 100644 --- a/src/fsharp/TypedTreePickle.fs +++ b/src/fsharp/TypedTreePickle.fs @@ -1978,20 +1978,6 @@ and p_tycon_objmodel_kind x st = | TTyconDelegate ss -> p_byte 3 st; p_slotsig ss st | TTyconEnum -> p_byte 4 st -and p_mustinline x st = - p_byte (match x with - | ValInline.PseudoVal -> 0 - | ValInline.Always -> 1 - | ValInline.Optional -> 2 - | ValInline.Never -> 3) st - -and p_basethis x st = - p_byte (match x with - | BaseVal -> 0 - | CtorThisVal -> 1 - | NormalVal -> 2 - | MemberThisVal -> 3) st - and p_vrefFlags x st = match x with | NormalValUse -> p_byte 0 st @@ -2278,22 +2264,6 @@ and u_tycon_objmodel_kind st = | 4 -> TTyconEnum | _ -> ufailwith st "u_tycon_objmodel_kind" -and u_mustinline st = - match u_byte st with - | 0 -> ValInline.PseudoVal - | 1 -> ValInline.Always - | 2 -> ValInline.Optional - | 3 -> ValInline.Never - | _ -> ufailwith st "u_mustinline" - -and u_basethis st = - match u_byte st with - | 0 -> BaseVal - | 1 -> CtorThisVal - | 2 -> NormalVal - | 3 -> MemberThisVal - | _ -> ufailwith st "u_basethis" - and u_vrefFlags st = match u_byte st with | 0 -> NormalValUse @@ -2422,7 +2392,7 @@ and p_dtree_discrim x st = | DecisionTreeTest.ActivePatternCase _ -> pfailwith st "DecisionTreeTest.ActivePatternCase: only used during pattern match compilation" | DecisionTreeTest.Error _ -> pfailwith st "DecisionTreeTest.Error: only used during pattern match compilation" -and p_target (TTarget(a, b, _)) st = p_tup2 p_Vals p_expr (a, b) st +and p_target (TTarget(a, b, _, _)) st = p_tup2 p_Vals p_expr (a, b) st and p_bind (TBind(a, b, _)) st = p_tup2 p_Val p_expr (a, b) st and p_lval_op_kind x st = @@ -2453,7 +2423,7 @@ and u_dtree_discrim st = | 4 -> u_tup2 u_int u_ty st |> DecisionTreeTest.ArrayLength | _ -> ufailwith st "u_dtree_discrim" -and u_target st = let a, b = u_tup2 u_Vals u_expr st in (TTarget(a, b, DebugPointForTarget.No)) +and u_target st = let a, b = u_tup2 u_Vals u_expr st in (TTarget(a, b, DebugPointForTarget.No, None)) and u_bind st = let a = u_Val st in let b = u_expr st in TBind(a, b, DebugPointAtBinding.NoneAtSticky) @@ -2598,7 +2568,7 @@ and p_expr expr st = | Expr.LetRec (a, b, c, _) -> p_byte 7 st; p_tup3 p_binds p_expr p_dummy_range (a, b, c) st | Expr.Let (a, b, c, _) -> p_byte 8 st; p_tup3 p_bind p_expr p_dummy_range (a, b, c) st | Expr.Match (_, a, b, c, d, e) -> p_byte 9 st; p_tup5 p_dummy_range p_dtree p_targets p_dummy_range p_ty (a, b, c, d, e) st - | Expr.Obj (_, b, c, d, e, f, g) -> p_byte 10 st; p_tup6 p_ty (p_option p_Val) p_expr p_methods p_intfs p_dummy_range (b, c, d, e, f, g) st + | Expr.Obj (_, b, c, d, e, f, g) -> p_byte 10 st; p_tup6 p_ty (p_option p_Val) p_expr p_methods p_intfs p_dummy_range (b, c, d, e, f, g) st | Expr.StaticOptimization (a, b, c, d) -> p_byte 11 st; p_tup4 p_constraints p_expr p_expr p_dummy_range (a, b, c, d) st | Expr.TyChoose (a, b, c) -> p_byte 12 st; p_tup3 p_tyar_specs p_expr p_dummy_range (a, b, c) st | Expr.Quote (ast, _, _, m, ty) -> p_byte 13 st; p_tup3 p_expr p_dummy_range p_ty (ast, m, ty) st @@ -2624,7 +2594,8 @@ and u_expr st = let b = u_expr st let c = u_int st let d = u_dummy_range st - Expr.Sequential (a, b, (match c with 0 -> NormalSeq | 1 -> ThenDoSeq | _ -> ufailwith st "specialSeqFlag"), DebugPointAtSequential.StmtOnly, d) + let dir = match c with 0 -> NormalSeq | 1 -> ThenDoSeq | _ -> ufailwith st "specialSeqFlag" + Expr.Sequential (a, b, dir, DebugPointAtSequential.SuppressStmt, d) | 4 -> let a0 = u_option u_Val st let b0 = u_option u_Val st let b1 = u_Vals st diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index 8642d6c56c9..1f9b6f9c615 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -2564,7 +2564,7 @@ type internal FsiInteractionProcessor let expr = parseExpression tokenizer let m = expr.Range // Make this into "(); expr" to suppress generalization and compilation-as-function - let exprWithSeq = SynExpr.Sequential (DebugPointAtSequential.ExprOnly, true, SynExpr.Const (SynConst.Unit,m.StartRange), expr, m) + let exprWithSeq = SynExpr.Sequential (DebugPointAtSequential.SuppressExpr, true, SynExpr.Const (SynConst.Unit,m.StartRange), expr, m) mainThreadProcessParsedExpression ctok errorLogger (exprWithSeq, istate)) |> commitResult diff --git a/src/fsharp/lib.fs b/src/fsharp/lib.fs index ef4785546b3..837c0eec8be 100755 --- a/src/fsharp/lib.fs +++ b/src/fsharp/lib.fs @@ -237,6 +237,24 @@ let p23 (_x, y, _z) = y let p33 (_x, _y, z) = z +let p14 (x1, _x2, _x3, _x4) = x1 + +let p24 (_x1, x2, _x3, _x4) = x2 + +let p34 (_x1, _x2, x3, _x4) = x3 + +let p44 (_x1, _x2, _x3, x4) = x4 + +let p15 (x1, _x2, _x3, _x4, _x5) = x1 + +let p25 (_x1, x2, _x3, _x4, _x5) = x2 + +let p35 (_x1, _x2, x3, _x4, _x5) = x3 + +let p45 (_x1, _x2, _x3, x4, _x5) = x4 + +let p55 (_x1, _x2, _x3, _x4, x5) = x5 + let map1Of2 f (a1, a2) = (f a1, a2) let map2Of2 f (a1, a2) = (a1, f a2) diff --git a/src/fsharp/lib.fsi b/src/fsharp/lib.fsi index f7816c129b0..5cad69e4e81 100644 --- a/src/fsharp/lib.fsi +++ b/src/fsharp/lib.fsi @@ -160,6 +160,24 @@ val p23: _x:'a * y:'b * _z:'c -> 'b val p33: _x:'a * _y:'b * z:'c -> 'c +val p14: x1:'a * _x2:'b * _x3:'c * _x4:'d -> 'a + +val p24: _x1:'a * x2:'b * _x3:'c * _x4:'d -> 'b + +val p34: _x1:'a * _x2:'b * x3:'c * _x4:'d -> 'c + +val p44: _x1:'a * _x2:'b * _x3:'c * x4:'d -> 'd + +val p15: x1:'a * _x2:'b * _x3:'c * _x4:'d * _x5:'e -> 'a + +val p25: _x1:'a * x2:'b * _x3:'c * _x4:'d * _x5:'e -> 'b + +val p35: _x1:'a * _x2:'b * x3:'c * _x4:'d * _x5:'e -> 'c + +val p45: _x1:'a * _x2:'b * _x3:'c * x4:'d * _x5:'e -> 'd + +val p55: _x1:'a * _x2:'b * _x3:'c * _x4:'d * x5:'e -> 'e + val map1Of2: f:('a -> 'b) -> a1:'a * a2:'c -> 'b * 'c val map2Of2: f:('a -> 'b) -> a1:'c * a2:'a -> 'c * 'b diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 334e6d7409c..f31b99b10c8 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -8,14 +8,14 @@ open System open Internal.Utilities open Internal.Utilities.Text.Parsing +open Internal.Utilities.Library +open Internal.Utilities.Library.Extras open FSharp.Compiler open FSharp.Compiler.AbstractIL open FSharp.Compiler.AbstractIL -open Internal.Utilities.Library open FSharp.Compiler.ErrorLogger open FSharp.Compiler.Features -open Internal.Utilities.Library.Extras open FSharp.Compiler.ParseHelpers open FSharp.Compiler.Syntax open FSharp.Compiler.Syntax.PrettyNaming @@ -3354,7 +3354,7 @@ typedSeqExprEOF: seqExpr: | declExpr seps seqExpr - { SynExpr.Sequential (DebugPointAtSequential.Both, true, $1, $3, unionRanges $1.Range $3.Range) } + { SynExpr.Sequential (DebugPointAtSequential.SuppressNeither, true, $1, $3, unionRanges $1.Range $3.Range) } | declExpr seps { $1 } @@ -3363,10 +3363,10 @@ seqExpr: { $1 } | declExpr THEN seqExpr %prec prec_then_before - { SynExpr.Sequential (DebugPointAtSequential.Both, false, $1, $3, unionRanges $1.Range $3.Range ) } + { SynExpr.Sequential (DebugPointAtSequential.SuppressNeither, false, $1, $3, unionRanges $1.Range $3.Range ) } | declExpr OTHEN OBLOCKBEGIN typedSeqExpr oblockend %prec prec_then_before - { SynExpr.Sequential (DebugPointAtSequential.Both, false, $1, $4, unionRanges $1.Range $4.Range) } + { SynExpr.Sequential (DebugPointAtSequential.SuppressNeither, false, $1, $4, unionRanges $1.Range $4.Range) } | hardwhiteLetBindings %prec prec_args_error { let hwlb, m = $1 diff --git a/src/fsharp/range.fs b/src/fsharp/range.fs index 690420ba7e5..db51b5b8f45 100755 --- a/src/fsharp/range.fs +++ b/src/fsharp/range.fs @@ -58,6 +58,15 @@ type Position(code:int64) = and pos = Position +[] +type RangeDebugPointKind = + | None + | While + | For + | Try + | Binding + | Finally + [] module RangeImpl = [] @@ -78,6 +87,9 @@ module RangeImpl = [] let isSyntheticBitCount = 1 + [] + let debugPointKindBitCount = 3 + [] let fileIndexShift = 0 @@ -97,33 +109,40 @@ module RangeImpl = let isSyntheticShift = 58 [] - let fileIndexMask = 0b0000000000000000000000000000000000000000111111111111111111111111L + let debugPointKindShift = 59 + + [] + let fileIndexMask = 0b0000000000000000000000000000000000000000111111111111111111111111L [] - let startColumnMask = 0b0000000000000000000011111111111111111111000000000000000000000000L + let startColumnMask = 0b0000000000000000000011111111111111111111000000000000000000000000L [] - let endColumnMask = 0b1111111111111111111100000000000000000000000000000000000000000000L + let endColumnMask = 0b1111111111111111111100000000000000000000000000000000000000000000L [] - let startLineMask = 0b0000000000000000000000000000000001111111111111111111111111111111L + let startLineMask = 0b0000000000000000000000000000000001111111111111111111111111111111L [] - let heightMask = 0b0000001111111111111111111111111110000000000000000000000000000000L + let heightMask = 0b0000001111111111111111111111111110000000000000000000000000000000L [] - let isSyntheticMask = 0b0000010000000000000000000000000000000000000000000000000000000000L + let isSyntheticMask = 0b0000010000000000000000000000000000000000000000000000000000000000L + + [] + let debugPointKindMask= 0b0011100000000000000000000000000000000000000000000000000000000000L #if DEBUG let _ = assert (posBitCount <= 64) let _ = assert (fileIndexBitCount + startColumnBitCount + endColumnBitCount <= 64) - let _ = assert (startLineBitCount + heightBitCount + isSyntheticBitCount <= 64) + let _ = assert (startLineBitCount + heightBitCount + isSyntheticBitCount + debugPointKindBitCount <= 64) let _ = assert (startColumnShift = fileIndexShift + fileIndexBitCount) let _ = assert (endColumnShift = startColumnShift + startColumnBitCount) let _ = assert (heightShift = startLineShift + startLineBitCount) let _ = assert (isSyntheticShift = heightShift + heightBitCount) + let _ = assert (debugPointKindShift = isSyntheticShift + isSyntheticBitCount) let _ = assert (fileIndexMask = mask64 fileIndexShift fileIndexBitCount) let _ = assert (startLineMask = mask64 startLineShift startLineBitCount) @@ -131,6 +150,7 @@ module RangeImpl = let _ = assert (heightMask = mask64 heightShift heightBitCount) let _ = assert (endColumnMask = mask64 endColumnShift endColumnBitCount) let _ = assert (isSyntheticMask = mask64 isSyntheticShift isSyntheticBitCount) + let _ = assert (debugPointKindMask = mask64 debugPointKindShift debugPointKindBitCount) #endif @@ -229,6 +249,15 @@ type Range(code1:int64, code2: int64) = member r.IsSynthetic = int32((code2 &&& isSyntheticMask) >>> isSyntheticShift) <> 0 + member r.DebugPointKind = + match int32((code2 &&& debugPointKindMask) >>> debugPointKindShift) with + | 1 -> RangeDebugPointKind.While + | 2 -> RangeDebugPointKind.For + | 3 -> RangeDebugPointKind.Try + | 4 -> RangeDebugPointKind.Finally + | 5 -> RangeDebugPointKind.Binding + | _ -> RangeDebugPointKind.None + member r.Start = pos (r.StartLine, r.StartColumn) member r.End = pos (r.EndLine, r.EndColumn) @@ -245,6 +274,17 @@ type Range(code1:int64, code2: int64) = member r.MakeSynthetic() = range(code1, code2 ||| isSyntheticMask) + member r.NoteDebugPoint(kind) = + let code = + match kind with + | RangeDebugPointKind.None -> 0 + | RangeDebugPointKind.While -> 1 + | RangeDebugPointKind.For -> 2 + | RangeDebugPointKind.Try -> 3 + | RangeDebugPointKind.Finally -> 4 + | RangeDebugPointKind.Binding -> 5 + range(code1, code2 ||| (int64 code <<< debugPointKindShift)) + member r.Code1 = code1 member r.Code2 = code2 @@ -273,7 +313,7 @@ type Range(code1:int64, code2: int64) = override r.GetHashCode() = hash code1 + hash code2 - override r.ToString() = sprintf "%s (%d,%d--%d,%d) IsSynthetic=%b" r.FileName r.StartLine r.StartColumn r.EndLine r.EndColumn r.IsSynthetic + override r.ToString() = sprintf "%s (%d,%d--%d,%d)" r.FileName r.StartLine r.StartColumn r.EndLine r.EndColumn and range = Range @@ -341,6 +381,10 @@ module Range = /// This is deliberately written in an allocation-free way, i.e. m1.Start, m1.End etc. are not called let unionRanges (m1:range) (m2:range) = if m1.FileIndex <> m2.FileIndex then m2 else + + // If all identical then return m1. This preserves DebugPointKind when no merging takes place + if m1.Code1 = m2.Code1 && m1.Code2 = m2.Code2 then m1 else + let b = if (m1.StartLine > m2.StartLine || (m1.StartLine = m2.StartLine && m1.StartColumn > m2.StartColumn)) then m2 else m1 diff --git a/src/fsharp/range.fsi b/src/fsharp/range.fsi index 1d2fcdb8634..13d604afee4 100755 --- a/src/fsharp/range.fsi +++ b/src/fsharp/range.fsi @@ -8,6 +8,15 @@ open System.Collections.Generic /// An index into a global tables of filenames type internal FileIndex = int32 +[] +type internal RangeDebugPointKind = + | None + | While + | For + | Try + | Binding + | Finally + /// Represents a position in a file [] type Position = @@ -69,9 +78,16 @@ type Range = /// service operations like dot-completion. member IsSynthetic: bool + /// When de-sugaring computation expressions we convert a debug point into a plain range, and then later + /// recover that the range definitely indicates a debug point. + member internal DebugPointKind: RangeDebugPointKind + /// Convert a range to be synthetic member internal MakeSynthetic: unit -> range + /// Note that a range indicates a debug point + member internal NoteDebugPoint: kind: RangeDebugPointKind -> range + /// Convert a range to string member internal ToShortString: unit -> string diff --git a/src/fsharp/service/FSharpParseFileResults.fs b/src/fsharp/service/FSharpParseFileResults.fs index 7b2ecf82a3f..d4b1ab9cd7c 100644 --- a/src/fsharp/service/FSharpParseFileResults.fs +++ b/src/fsharp/service/FSharpParseFileResults.fs @@ -524,7 +524,9 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, | SynInterpolatedStringPart.String _ -> () | SynInterpolatedStringPart.FillExpr (fillExpr, _) -> yield fillExpr ] - | SynExpr.YieldOrReturn (_, e, _) + | SynExpr.YieldOrReturn (_, e, m) -> + yield! checkRange m + yield! walkExpr false e | SynExpr.YieldOrReturnFrom (_, e, _) | SynExpr.DoBang (e, _) -> yield! checkRange e.Range @@ -615,8 +617,8 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, | SynExpr.SequentialOrImplicitYield (spSeq, e1, e2, _, _) | SynExpr.Sequential (spSeq, _, e1, e2, _) -> - yield! walkExpr (match spSeq with DebugPointAtSequential.ExprOnly -> false | _ -> true) e1 - yield! walkExpr (match spSeq with DebugPointAtSequential.StmtOnly -> false | _ -> true) e2 + yield! walkExpr (match spSeq with DebugPointAtSequential.SuppressExpr | DebugPointAtSequential.SuppressBoth -> false | _ -> true) e1 + yield! walkExpr (match spSeq with DebugPointAtSequential.SuppressStmt | DebugPointAtSequential.SuppressBoth -> false | _ -> true) e2 | SynExpr.IfThenElse (e1, e2, e3opt, spBind, _, _, _) -> yield! walkBindSeqPt spBind diff --git a/src/fsharp/symbols/Exprs.fs b/src/fsharp/symbols/Exprs.fs index c1b456e0948..74ac59496a0 100644 --- a/src/fsharp/symbols/Exprs.fs +++ b/src/fsharp/symbols/Exprs.fs @@ -1186,7 +1186,7 @@ module FSharpExprConvert = and ConvTargetsLinear cenv env tgs contF = match tgs with | [] -> contF [] - | TTarget(vars, rhs, _) :: rest -> + | TTarget(vars, rhs, _, _) :: rest -> let varsR = (List.rev vars) |> List.map (ConvVal cenv) ConvExprLinear cenv env rhs (fun targetR -> ConvTargetsLinear cenv env rest (fun restR -> diff --git a/src/fsharp/symbols/Symbols.fs b/src/fsharp/symbols/Symbols.fs index 0cf4f677a4f..8affc871220 100644 --- a/src/fsharp/symbols/Symbols.fs +++ b/src/fsharp/symbols/Symbols.fs @@ -1526,7 +1526,6 @@ type FSharpGenericParameterConstraint(cenv, cx: TyparConstraint) = override x.ToString() = "" type FSharpInlineAnnotation = - | PseudoValue | AlwaysInline | OptionalInline | NeverInline @@ -1746,7 +1745,6 @@ type FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = | None -> FSharpInlineAnnotation.OptionalInline | Some v -> match v.InlineInfo with - | ValInline.PseudoVal -> FSharpInlineAnnotation.PseudoValue | ValInline.Always -> FSharpInlineAnnotation.AlwaysInline | ValInline.Optional -> FSharpInlineAnnotation.OptionalInline | ValInline.Never -> FSharpInlineAnnotation.NeverInline diff --git a/src/fsharp/symbols/Symbols.fsi b/src/fsharp/symbols/Symbols.fsi index ba09617f18b..8cf040e5523 100644 --- a/src/fsharp/symbols/Symbols.fsi +++ b/src/fsharp/symbols/Symbols.fsi @@ -716,10 +716,7 @@ type FSharpGenericParameterConstraint = [] type FSharpInlineAnnotation = - /// Indicates the value is inlined and compiled code for the function does not exist - | PseudoValue - - /// Indicates the value is inlined but compiled code for the function still exists, e.g. to satisfy interfaces on objects, but that it is also always inlined + /// Indicates the value is always inlined in statically compiled code | AlwaysInline /// Indicates the value is optionally inlined diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index 5f0d33d8905..d5847712cb2 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -177,6 +177,11 @@ uvolnění prázdných znaků + + resumable state machines + resumable state machines + + single underscore pattern vzor s jedním podtržítkem @@ -237,6 +242,16 @@ Neplatná direktiva #{0} {1} + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. Klíčové slovo, které specifikuje konstantní literál jako argument parametru typu v poskytovatelích typů @@ -272,6 +287,11 @@ Hlavička zdroje začínající na posunu {0} má chybný formát. + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files Vytiskněte odvozená rozhraní všech kompilovaných souborů do přidružených souborů podpisu. @@ -352,11 +372,66 @@ Algoritmus {0} není podporovaný. + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers Registrovaní správci PackageManagers nepodporují #i. + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. Sadu .NET SDK pro tento skript nešlo určit. Pokud se skript nachází v adresáři používajícím global.json, zkontrolujte, jestli je nainstalovaná odpovídající sada .NET SDK. Výstup ze zadání {0} --version v adresáři {1} byl {2} a ukončovací kód byl {3}. @@ -407,6 +482,11 @@ Typy Byref nejsou v deklaraci otevřeného typu povolené. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' Neshoda v interpolovaném řetězci. Interpolované řetězce nemůžou používat specifikátory formátu %, pokud se každému z nich nezadá nějaký výraz, např. %d{{1+1}}. @@ -417,6 +497,11 @@ Neplatné zarovnání v interpolovaném řetězci + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions Použití [<Struct>] u hodnot, funkcí a metod je povolené jenom u částečných aktivních definic vzorů. @@ -447,6 +532,36 @@ Konstrukt let! ... and! ... se dá použít jen v případě, že tvůrce výpočetních výrazů definuje buď metodu {0}, nebo vhodné metody MergeSource a Bind. + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} Neplatný interpolovaný řetězec. {0} diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index b34d90b5d42..fca4225840d 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -177,6 +177,11 @@ Lockerung für Leerraum + + resumable state machines + resumable state machines + + single underscore pattern Muster mit einzelnem Unterstrich @@ -237,6 +242,16 @@ Ungültige Direktive "#{0} {1}" + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. Schlüsselwort, um ein konstantes Literal als Typparameterargument in Typanbietern anzugeben. @@ -272,6 +287,11 @@ Der Ressourcenheader, der am Offset {0} beginnt, ist fehlerhaft formatiert. + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files Drucken der abgeleiteten Schnittstellen aller Dateien an zugehörige Signaturdateien @@ -352,11 +372,66 @@ Algorithmus "{0}" wird nicht unterstützt + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers #i wird von den registrierten PackageManagers nicht unterstützt. + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. Das .NET SDK für dieses Skript konnte nicht ermittelt werden. Wenn sich das Skript in einem Verzeichnis mit "global.json" befindet, stellen Sie sicher, dass das entsprechende .NET SDK installiert ist. Ausgabe von "{0} --version" im Verzeichnis "{1}": {2}. Exitcode: {3}. @@ -407,6 +482,11 @@ Byref-Typen sind in einer Deklaration für offene Typen nicht zulässig. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' Konflikt in interpolierter Zeichenfolge. Interpolierte Zeichenfolgen dürfen keine Formatbezeichner vom Typ "%" verwenden, es sei denn, jeder erhält einen Ausdruck, z. B. "%d{{1+1}}" @@ -417,6 +497,11 @@ Ungültige Ausrichtung in interpolierter Zeichenfolge. + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions Die Verwendung von "[<Struct>]" für Werte, Funktionen und Methoden ist nur für partielle aktive Musterdefinitionen zulässig. @@ -447,6 +532,36 @@ Das Konstrukt "let! ... and! ..." kann nur verwendet werden, wenn der Berechnungsausdrucks-Generator entweder eine {0}-Methode oder geeignete MergeSource- und Bind-Methoden definiert. + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} Ungültige interpolierte Zeichenfolge. {0} diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index d0313a1bef2..075e38c13ca 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -177,6 +177,11 @@ relajación de espacio en blanco + + resumable state machines + resumable state machines + + single underscore pattern patrón de subrayado simple @@ -237,6 +242,16 @@ Directiva '#{0} {1}' no válida. + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. Palabra clave para especificar un literal de constante como argumento de parámetro de tipo en los proveedores de tipo. @@ -272,6 +287,11 @@ El encabezado de los recursos que comienza en el desplazamiento {0} está mal formado. + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files Imprimir las interfaces deducidas de todos los archivos de compilación en los archivos de signatura asociados @@ -352,11 +372,66 @@ No se admite el algoritmo '{0}' + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers Los elementos PackageManager registrados no admiten #i + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. No se pudo determinar el SDK de .NET para este script. Si el script está en un directorio que usa una instancia de "global.json", asegúrese de que el SDK de .NET pertinente esté instalado. La salida de "{0} --version" en el directorio "{1}" era "{2}", con el código de salida "{3}". @@ -407,6 +482,11 @@ No se permiten tipos byref en una declaración de tipo abierto. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' La cadena interpolada no coincide. Las cadenas interpoladas no pueden usar los especificadores de formato "%", a menos que se les proporcione una expresión individualmente; por ejemplo, "%d{{1+1}}". @@ -417,6 +497,11 @@ Alineación no válida en la cadena interpolada + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions El uso de «[<Struct>]» en valores, funciones y métodos solo se permite en definiciones de modelos activos parciales. @@ -447,6 +532,36 @@ La construcción "let! ... and! ..." solo se puede usar si el generador de expresiones de cálculo define un método "{0}" o bien los métodos "MergeSource" y "Bind" adecuados. + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} Cadena interpolada no válida. {0} diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index 605eb3abf33..5217a2741ce 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -177,6 +177,11 @@ assouplissement de la mise en retrait avec des espaces blancs + + resumable state machines + resumable state machines + + single underscore pattern modèle de trait de soulignement unique @@ -237,6 +242,16 @@ Directive non valide '#{0} {1}' + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. Mot clé permettant de spécifier une constante littérale en tant qu'argument de paramètre de type dans les fournisseurs de types. @@ -272,6 +287,11 @@ L'en-tête de ressource commençant au décalage {0} est mal formé. + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files Imprimer les interfaces inférées de tous les fichiers de compilation sur les fichiers de signature associés @@ -352,11 +372,66 @@ Algorithme '{0}' non pris en charge + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers #i n'est pas pris en charge par les PackageManagers inscrits + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. Le kit SDK .NET de ce script n'a pas pu être déterminé. Si le script se trouve dans un répertoire utilisant un fichier 'global.json', vérifiez que le kit SDK .NET approprié est installé. La sortie de '{0} --version' dans le répertoire '{1}' était '{2}', et le code de sortie était '{3}'. @@ -407,6 +482,11 @@ Les types Byref ne sont pas autorisés dans une déclaration de type ouverte. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' Incompatibilité dans la chaîne interpolée. Les chaînes interpolées ne peuvent pas utiliser les spécificateurs de format '%' à moins de recevoir une expression, par exemple '%d{{1+1}}' @@ -417,6 +497,11 @@ Alignement non valide dans la chaîne interpolée + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions L’utilisation de' [<Struct>] 'sur les valeurs, les fonctions et les méthodes n’est autorisée que sur les définitions de modèle actif partiel @@ -447,6 +532,36 @@ La construction 'let! ... and! ...' peut uniquement être utilisée si le générateur d'expressions de calcul définit une méthode '{0}' ou les méthodes 'MergeSource' et 'Bind' appropriées + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} Chaîne interpolée non valide. {0} diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index fe47cbae173..dc045bd4020 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -177,6 +177,11 @@ uso meno restrittivo degli spazi vuoti + + resumable state machines + resumable state machines + + single underscore pattern criterio per carattere di sottolineatura singolo @@ -237,6 +242,16 @@ Direttiva '#{0} {1}' non valida + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. Parola chiave per specificare un valore letterale di costante come argomento del parametro di tipo in Provider di tipi. @@ -272,6 +287,11 @@ L'intestazione di risorsa che inizia a partire dall'offset {0} non è valida. + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files Stampare le interfacce derivate di tutti i file di compilazione nei file di firma associati @@ -352,11 +372,66 @@ L'algoritmo '{0}' non è supportato + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers #i non è supportato dagli elementi PackageManager registrati + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. Non è stato possibile determinare la versione di .NET SDK per questo script. Se lo script si trova in una directory che usa un file 'global.json', assicurarsi che sia installata la versione pertinente di .NET SDK. L'output di '{0} --version' nella directory '{1}' è '{2}' e il codice di uscita è '{3}'. @@ -407,6 +482,11 @@ I tipi byref non sono consentiti in una dichiarazione di tipo aperto. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' Mancata corrispondenza nella stringa interpolata. Nelle stringhe interpolate non è possibile usare gli identificatori di formato '%' a meno che non si indichi un'espressione per ognuno di essi, ad esempio '%d{{1+1}}' @@ -417,6 +497,11 @@ Allineamento non valido nella stringa interpolata + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions L'utilizzo di '[<Struct>]' su valori, funzioni e metodi è consentito solo per definizioni di criteri attivi parziali @@ -447,6 +532,36 @@ È possibile usare il costrutto 'let! ... and! ...' solo se il generatore di espressioni di calcolo definisce un metodo '{0}' o metodi 'MergeSource' e 'Bind' appropriati + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} La stringa interpolata non è valida. {0} diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index f61f49b12aa..8509d0f8df5 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -177,6 +177,11 @@ 空白の緩和 + + resumable state machines + resumable state machines + + single underscore pattern 単一のアンダースコア パターン @@ -237,6 +242,16 @@ 無効なディレクティブ '#{0} {1}' + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. 定数リテラルを型プロバイダーの型パラメーター引数として指定するキーワード。 @@ -272,6 +287,11 @@ オフセット {0} で始まるリソース ヘッダーの形式に誤りがあります。 + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files すべてのコンパイル ファイルの推定されたインターフェイスを関連する署名ファイルに印刷します @@ -357,6 +377,61 @@ 登録された PackageManager によって、#i はサポートされていません + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. このスクリプトの .NET SDK を特定できませんでした。このスクリプトが、'global.json' が使用されているディレクトリにある場合は、関連する .NET SDK がインストールされていることを確認してください。ディレクトリ '{1}' の '{0} --version' からの出力は '{2}' で、終了コードは '{3}' でした。 @@ -407,6 +482,11 @@ Byref 型は、オープン型宣言では使用できません。 + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' 補間された文字列が一致しません。'%d{{1+1}}' などの式が指定されている場合を除き、補間された文字列では '%' 書式指定子を使用できません @@ -417,6 +497,11 @@ 補間された文字列内の配置が無効です + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions 値、関数、およびメソッドでの '[<Struct>]' は、部分的なアクティブ パターンの定義でのみ使うことができます @@ -447,6 +532,36 @@ 'let! ... and! ...' コンストラクトは、コンピュテーション式ビルダーが '{0}' メソッドまたは適切な 'MergeSource' および 'Bind' メソッドのいずれかを定義している場合にのみ使用できます + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} 補間された文字列が無効です。{0} diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index 98557a0a5c9..e5fb6dd8044 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -177,6 +177,11 @@ 공백 완화 + + resumable state machines + resumable state machines + + single underscore pattern 단일 밑줄 패턴 @@ -237,6 +242,16 @@ 잘못된 지시문 '#{0} {1}' + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. 상수 리터럴을 형식 공급자의 형식 매개 변수 인수로 지정하는 키워드입니다. @@ -272,6 +287,11 @@ 오프셋 {0}에서 시작하는 리소스 헤더의 형식이 잘못되었습니다. + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files 모든 컴파일 파일의 유추된 인터페이스를 관련 서명 파일로 인쇄합니다. @@ -352,11 +372,66 @@ {0}' 알고리즘은 지원되지 않습니다. + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers #i는 등록된 PackageManagers에서 지원하지 않습니다. + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. 이 스크립트에 대한 .NET SDK를 확인할 수 없습니다. 스크립트가 'global.json'을 사용하는 디렉터리에 있는 경우 관련 .NET SDK가 설치되어 있는지 확인하세요. '{1}' 디렉터리에 있는 '{0} --version'의 출력은 '{2}'이고 종료 코드는 '{3}'입니다. @@ -407,6 +482,11 @@ Byref 형식은 개방형 형식 선언에서 허용되지 않습니다. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' 보간 문자열의 불일치. 각 보간 문자열에 식(예: '%d{{1+1}}')이 지정되지 않는 한 '%' 형식 지정자를 사용할 수 없습니다. @@ -417,6 +497,11 @@ 보간 문자열의 잘못된 정렬 + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions 값, 함수 및 메서드에 '[<Struct>]'을(를) 사용하는 것은 부분 활성 패턴 정의에서만 허용됩니다. @@ -447,6 +532,36 @@ 'let! ... and! ...' 구문은 계산 식 작성기에서 '{0}' 메서드 또는 적절한 'MergeSource' 및 'Bind' 메서드를 정의한 경우에만 사용할 수 있습니다. + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} 잘못된 보간 문자열. {0} diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index c707761e682..d3e018ef671 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -177,6 +177,11 @@ rozluźnianie reguł dotyczących odstępów + + resumable state machines + resumable state machines + + single underscore pattern wzorzec z pojedynczym podkreśleniem @@ -237,6 +242,16 @@ Nieprawidłowa dyrektywa „#{0} {1}” + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. Słowo kluczowe na potrzeby określania literału stałej jako argumentu parametru typu w przypadku dostawców typów. @@ -272,6 +287,11 @@ Nagłówek zasobu rozpoczynający się od przesunięcia {0} jest nieprawidłowo sformułowany. + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files Drukowanie wywnioskowanych interfejsów wszystkich plików kompilacji do skojarzonych plików sygnatur @@ -352,11 +372,66 @@ Algorytm „{0}” nie jest obsługiwany + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers Element #i nie jest obsługiwany przez zarejestrowanych menedżerów pakietów + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. Nie można określić zestawu .NET SDK dla tego skryptu. Jeśli skrypt znajduje się w katalogu korzystającym z pliku „global.json”, upewnij się, że zainstalowano odpowiedni zestaw .NET SDK. Dane wyjściowe polecenia „{0} --version” w katalogu „{1}” to „{2}”, a kod zakończenia to „{3}”. @@ -407,6 +482,11 @@ Typy ByRef są niedozwolone w deklaracji typu otwartego. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' Niezgodność w interpolowanym ciągu. W interpolowanych ciągach nie można używać specyfikatorów formatu „%”, chyba że każdemu z nich odpowiada wyrażenie, na przykład „%d{{1+1}}”. @@ -417,6 +497,11 @@ Nieprawidłowe wyrównanie w ciągu interpolowanym + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions Używanie elementu "[<Struct>]" na wartościach, funkcjach i metodach jest dozwolone tylko w definicjach częściowo aktywnego wzorca @@ -447,6 +532,36 @@ Konstrukcji „let! ... and! ...” można użyć tylko wtedy, gdy konstruktor wyrażeń obliczeniowych definiuje metodę „{0}” lub odpowiednie metody „MergeSource” i „Bind” + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} Nieprawidłowy ciąg interpolowany. {0} diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index 171b10911ce..9e5a38bac97 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -177,6 +177,11 @@ atenuação de espaço em branco + + resumable state machines + resumable state machines + + single underscore pattern padrão de sublinhado simples @@ -237,6 +242,16 @@ Diretriz inválida '#{0} {1}' + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. Palavra-chave para especificar um literal constante como um argumento de parâmetro de tipo nos Provedores de Tipo. @@ -272,6 +287,11 @@ O cabeçalho do recurso que começa no deslocamento {0} está malformado. + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files Imprimir as interfaces inferidas de todos os arquivos de compilação para os arquivos de assinatura associados @@ -352,11 +372,66 @@ Algoritmo '{0}' sem suporte + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers O PackageManagers registrado não dá suporte a #i + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. Não foi possível determinar o SDK do .NET para esse script. Se o script estiver em um diretório usando um 'global.json', verifique se o SDK relevante do .NET está instalado. A saída de '{0} --version' no diretório '{1}' foi: '{2}' e o código de saída foi '{3}'. @@ -407,6 +482,11 @@ Os tipos Byref não são permitidos em uma declaração de tipo aberto. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' Incompatibilidade na cadeia de caracteres interpolada. As cadeias de caracteres interpoladas não podem usar especificadores de formato '%', a menos que cada um receba uma expressão, por exemplo, '%d{{1+1}}' @@ -417,6 +497,11 @@ Alinhamento inválido na cadeia de caracteres interpolada + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions O uso de '[<Struct>]' em valores, funções e métodos somente é permitido em definições de padrões ativos parciais @@ -447,6 +532,36 @@ O constructo 'let! ... and! ...' só pode ser usado se o construtor de expressões de computação definir um método '{0}' ou um método 'MergeSource' ou 'Bind' apropriado + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} Cadeia de caracteres interpolada inválida. {0} diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index 07e804054e2..1fc4e95e281 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -177,6 +177,11 @@ уменьшение строгости для пробелов + + resumable state machines + resumable state machines + + single underscore pattern шаблон с одним подчеркиванием @@ -237,6 +242,16 @@ Недопустимая директива "#{0} {1}" + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. Ключевое слово для указания константного литерала в качестве аргумента параметра типа в поставщиках типов. @@ -272,6 +287,11 @@ Заголовок ресурса некорректен начиная со смещения {0}. + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files Печать определяемых интерфейсов всех файлов компиляции в связанные файлы подписей @@ -352,11 +372,66 @@ Алгоритм "{0}" не поддерживается + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers #i не поддерживается зарегистрированными диспетчерами пакетов + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. Не удалось определить пакет SDK .NET для этого сценария. Если сценарий находится в каталоге с использованием "global.json", убедитесь, что установлен соответствующий пакет SDK .NET. Выходные данные команды "{0} --version" в каталоге "{1}" — "{2}", а код выхода — "{3}". @@ -407,6 +482,11 @@ Типы ByRef запрещены в объявлении открытого типа. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' Несоответствие в интерполированной строке. В интерполированных строках запрещено использовать описатели формата "%", если только каждому из них не назначено выражение, например "'%d{{1+1}}". @@ -417,6 +497,11 @@ Недопустимое выравнивание в интерполированной строке + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions Использование "[<Struct>]" для значений, функций и методов разрешено только для определений частичных активных шаблонов @@ -447,6 +532,36 @@ Конструкцию "let! ... and! ..." можно использовать только в том случае, если построитель выражений с вычислениями определяет либо метод "{0}", либо соответствующие методы "MergeSource" и "Bind" + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} Недопустимая интерполированная строка. {0} diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index d3c75fd8108..c86c84d24de 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -177,6 +177,11 @@ boşluk genişlemesi + + resumable state machines + resumable state machines + + single underscore pattern tek alt çizgi deseni @@ -237,6 +242,16 @@ Geçersiz yönerge '#{0} {1}' + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. Tür Sağlayıcılarında tür parametresi bağımsız değişkeni olarak sabit değişmez değeri belirtmek için anahtar sözcük. @@ -272,6 +287,11 @@ {0} uzaklığında başlayan kaynak üst bilgisi hatalı biçimlendirilmiş. + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files Tüm derleme dosyalarının çıkarsanan arabirimlerini ilişkili imza dosyalarına yazdır @@ -352,11 +372,66 @@ {0}' algoritması desteklenmiyor + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers #i, kayıtlı PackageManagers tarafından desteklenmiyor + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. Bu betik için .NET SDK belirlenemedi. Betik 'global.json' kullanan bir dizindeyse, ilgili .NET SDK'nın yüklü olduğundan emin olun. '{1}' dizinindeki '{0} --version' çıkışı: '{2}' ve çıkış kodu: '{3}'. @@ -407,6 +482,11 @@ Açık tür bildiriminde Byref türlerine izin verilmez. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' Düz metin arasına kod eklenmiş dizede uyuşmazlık. Düz metin arasına kod eklenmiş dizeler, her birine '%d{{1+1}}' gibi bir ifade verilmedikçe '%' biçim belirticilerini kullanamaz @@ -417,6 +497,11 @@ Düz metin arasına kod eklenmiş dizede geçersiz hizalama + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions Değerlerde, işlevlerde ve yöntemlerde '[<Struct>]' kullanımına yalnızca kısmi etkin desen tanımlarında izin veriliyor @@ -447,6 +532,36 @@ 'let! ... and! ...' yapısı, yalnızca hesaplama ifadesi oluşturucu bir '{0}' metodunu ya da uygun 'MergeSource' ve 'Bind' metotlarını tanımlarsa kullanılabilir + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} Geçersiz düz metin arasına kod eklenmiş dize. {0} diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index f4dc42711ea..5370593ba3d 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -177,6 +177,11 @@ 空格松弛法 + + resumable state machines + resumable state machines + + single underscore pattern 单下划线模式 @@ -237,6 +242,16 @@ 无效的指令“#{0} {1}” + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. 用于将常量文本指定为类型提供程序中的类型形参实参的关键字。 @@ -272,6 +287,11 @@ 以偏移量 {0} 开始的资源标头格式不正确。 + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files 将所有编译文件的推断接口打印到关联的签名文件 @@ -352,11 +372,66 @@ 不支持算法“{0}” + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers 注册的 PackageManager 不支持 #i + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. 无法确定此脚本的 .NET SDK。如果脚本在使用 "global.json" 的目录中,请确保已安装相关的 .NET SDK。目录“{1}”中 "{0} --version" 的输出为“{2}”,退出代码为“{3}”。 @@ -407,6 +482,11 @@ 在开放类型声明中不允许使用 Byref 类型。 + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' 在内插字符串中不匹配。内插字符串不会使用 "%" 格式说明符,除非为每个字符串提供像 "'%d{{1+1}}" 这样的表达式 @@ -417,6 +497,11 @@ 内插字符串中的对齐无效 + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions 只允许在部分活动模式定义中对值、函数和方法使用 "[<Struct>]" @@ -447,6 +532,36 @@ 仅当计算表达式生成器定义了 "{0}" 方法或适当的 "MergeSource" 和 "Bind" 方法时,才可以使用 "let! ... and! ..." 构造 + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} 内插字符串无效。{0} diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index 137fa6b4fd6..7f9913fec3d 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -177,6 +177,11 @@ 空白字元放寬 + + resumable state machines + resumable state machines + + single underscore pattern 單一底線模式 @@ -237,6 +242,16 @@ 無效的指示詞 '#{0} {1}' + + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + The resumable code construct '{0}' may only be used in inlined code protected by 'if __useResumableCode then ...' and the overall composition must form valid resumable code. + + + + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + The 'InlineIfLambda' attribute is present in the signature but not the implementation. + + Keyword to specify a constant literal as a type parameter argument in Type Providers. 用於在型別提供者中,將常數常值指定為型別參數引數的關鍵字。 @@ -272,6 +287,11 @@ 從位移 {0} 開始的資源標頭格式錯誤。 + + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + The value '{0}' was marked 'InlineIfLambda' but was not determined to have a lambda value. This warning is for informational purposes only. + + Print the inferred interfaces of all compilation files to associated signature files 將所有編譯檔案的推斷介面列印至相關聯的簽章檔案 @@ -352,11 +372,66 @@ 不支援演算法 '{0}' + + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + A target label for __resumeAt was not statically determined. A __resumeAt with a non-static target label may only appear at the start of a resumable code method + + + + A fast integer for loop may not contain resumption points + A fast integer for loop may not contain resumption points + + + + A 'let rec' occured in the resumable code specification + A 'let rec' occured in the resumable code specification + + + + The 'with' block of a try/with may not contain resumption points + The 'with' block of a try/with may not contain resumption points + + + + A try/finally may not contain resumption points + A try/finally may not contain resumption points + + + + A delegate or function producing resumable code in a state machine has type parameters + A delegate or function producing resumable code in a state machine has type parameters + + + + A resumable code invocation at '{0}' could not be reduced + A resumable code invocation at '{0}' could not be reduced + + + + The resumable code value(s) '{0}' does not have a definition + The resumable code value(s) '{0}' does not have a definition + + #i is not supported by the registered PackageManagers 註冊的 PackageManagers 不支援 #i + + The state machine has an unexpected form + The state machine has an unexpected form + + + + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + This state machine is not statically compilable. {0}. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + + + + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + This state machine is not statically compilable and no alternative is available. {0}. Use an 'if __useResumableCode then <state-machine> else <alternative>' to give an alternative. + + The .NET SDK for this script could not be determined. If the script is in a directory using a 'global.json' then ensure the relevant .NET SDK is installed. The output from '{0} --version' in the directory '{1}' was: '{2}' and the exit code was '{3}'. 無法判斷這個指令碼的 .NET SDK。如果指令碼位於使用 'global.json' 的目錄中,請確認已安裝相關的 .NET SDK。目錄 '{1}' 中 '{0} --version' 的輸出為: '{2}',結束代碼為 '{3}'。 @@ -407,6 +482,11 @@ 開放式類型宣告中不允許 Byref 類型。 + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. + + Mismatch in interpolated string. Interpolated strings may not use '%' format specifiers unless each is given an expression, e.g. '%d{{1+1}}' 插補字串不相符。除非每個插補字串都有一個運算式,否則不可使用 '%' 格式指定名稱,例如 '%d{{1+1}}' @@ -417,6 +497,11 @@ 插補字串中的對齊無效 + + The construct '{0}' may only be used in valid resumable code. + The construct '{0}' may only be used in valid resumable code. + + The use of '[<Struct>]' on values, functions and methods is only allowed on partial active pattern definitions 只允許在部分現用模式定義上對值、函式和方法使用 '[<Struct>]' @@ -447,6 +532,36 @@ 只有在計算運算式產生器定義 '{0}' 方法或正確的 'MergeSource' 和 'Bind' 方法時,才可使用 'let! ... and! ...' 建構 + + Invalid resumable code. A resumable code parameter must be of delegate or function type + Invalid resumable code. A resumable code parameter must be of delegate or function type + + + + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + Invalid resumable code. Resumable code parameter must have name beginning with '__expand' + + + + Invalid resumable code. A 'let rec' occured in the resumable code specification + Invalid resumable code. A 'let rec' occured in the resumable code specification + + + + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + Invalid resumable code. Any method of function accepting or returning resumable code must be marked 'inline' + + + + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + Resumable code invocation. Suppress this warning if you are defining new low-level resumable code in terms of existing resumable code. + + + + Using resumable code or resumable state machines requires /langversion:preview + Using resumable code or resumable state machines requires /langversion:preview + + Invalid interpolated string. {0} 插補字串無效。{0} diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TailCalls.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TailCalls.fs index 2e37d06e92a..cbe51a7a381 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TailCalls.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TailCalls.fs @@ -25,22 +25,16 @@ let run() = let x = 0 in foo(x,5) .method public static void foo(int32 x, !!a y) cil managed { - - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_0, - int32 V_1) + + .maxstack 8 IL_0000: ldstr "%d" IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_000f: stloc.0 - IL_0010: ldarg.0 - IL_0011: stloc.1 - IL_0012: ldloc.0 - IL_0013: ldloc.1 - IL_0014: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0019: pop - IL_001a: ret - } + IL_000f: ldarg.0 + IL_0010: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0015: pop + IL_0016: ret + } """ """ .method public static void run() cil managed @@ -110,28 +104,22 @@ let run() = let mutable x = 0 in foo &x &x 5 int32& y, !!a z) cil managed { - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 - 00 00 00 00 ) - - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_0, - int32 V_1) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 03 00 00 00 01 00 00 00 01 00 00 00 01 00 + 00 00 00 00 ) + + .maxstack 8 IL_0000: ldstr "%d" IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_000f: stloc.0 - IL_0010: ldarg.0 - IL_0011: ldobj [runtime]System.Int32 - IL_0016: ldarg.1 - IL_0017: ldobj [runtime]System.Int32 - IL_001c: add - IL_001d: stloc.1 - IL_001e: ldloc.0 - IL_001f: ldloc.1 - IL_0020: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0025: pop - IL_0026: ret - } + IL_000f: ldarg.0 + IL_0010: ldobj [runtime]System.Int32 + IL_0015: ldarg.1 + IL_0016: ldobj [runtime]System.Int32 + IL_001b: add + IL_001c: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0021: pop + IL_0022: ret + } """ """ .method public static void run() cil managed @@ -167,23 +155,17 @@ let run() = let mutable x = 0 in foo(&x,5) .method public static void foo(int32& x, !!a y) cil managed { - - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_0, - int32 V_1) + + .maxstack 8 IL_0000: ldstr "%d" IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_000f: stloc.0 - IL_0010: ldarg.0 - IL_0011: ldobj [runtime]System.Int32 - IL_0016: stloc.1 - IL_0017: ldloc.0 - IL_0018: ldloc.1 - IL_0019: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_001e: pop - IL_001f: ret - } + IL_000f: ldarg.0 + IL_0010: ldobj [runtime]System.Int32 + IL_0015: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_001a: pop + IL_001b: ret + } """ """ .method public static void run() cil managed @@ -218,26 +200,20 @@ let run() = let mutable x = 0 in foo(&x,&x,5) int32& y, !!a z) cil managed { - - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_0, - int32 V_1) + + .maxstack 8 IL_0000: ldstr "%d" IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [runtime]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_000f: stloc.0 - IL_0010: ldarg.0 - IL_0011: ldobj [runtime]System.Int32 - IL_0016: ldarg.1 - IL_0017: ldobj [runtime]System.Int32 - IL_001c: add - IL_001d: stloc.1 - IL_001e: ldloc.0 - IL_001f: ldloc.1 - IL_0020: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0025: pop - IL_0026: ret - } + IL_000f: ldarg.0 + IL_0010: ldobj [runtime]System.Int32 + IL_0015: ldarg.1 + IL_0016: ldobj [runtime]System.Int32 + IL_001b: add + IL_001c: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0021: pop + IL_0022: ret + } """ """ .method public static void run() cil managed diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected index e0ad9b06d0c..aca4508f14c 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstandard.expected @@ -4727,7 +4727,6 @@ FSharp.Compiler.Symbols.FSharpInlineAnnotation+Tags: Int32 AggressiveInline FSharp.Compiler.Symbols.FSharpInlineAnnotation+Tags: Int32 AlwaysInline FSharp.Compiler.Symbols.FSharpInlineAnnotation+Tags: Int32 NeverInline FSharp.Compiler.Symbols.FSharpInlineAnnotation+Tags: Int32 OptionalInline -FSharp.Compiler.Symbols.FSharpInlineAnnotation+Tags: Int32 PseudoValue FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean Equals(FSharp.Compiler.Symbols.FSharpInlineAnnotation) FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean Equals(System.Object) FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean Equals(System.Object, System.Collections.IEqualityComparer) @@ -4735,22 +4734,18 @@ FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean IsAggressiveInline FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean IsAlwaysInline FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean IsNeverInline FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean IsOptionalInline -FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean IsPseudoValue FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean get_IsAggressiveInline() FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean get_IsAlwaysInline() FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean get_IsNeverInline() FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean get_IsOptionalInline() -FSharp.Compiler.Symbols.FSharpInlineAnnotation: Boolean get_IsPseudoValue() FSharp.Compiler.Symbols.FSharpInlineAnnotation: FSharp.Compiler.Symbols.FSharpInlineAnnotation AggressiveInline FSharp.Compiler.Symbols.FSharpInlineAnnotation: FSharp.Compiler.Symbols.FSharpInlineAnnotation AlwaysInline FSharp.Compiler.Symbols.FSharpInlineAnnotation: FSharp.Compiler.Symbols.FSharpInlineAnnotation NeverInline FSharp.Compiler.Symbols.FSharpInlineAnnotation: FSharp.Compiler.Symbols.FSharpInlineAnnotation OptionalInline -FSharp.Compiler.Symbols.FSharpInlineAnnotation: FSharp.Compiler.Symbols.FSharpInlineAnnotation PseudoValue FSharp.Compiler.Symbols.FSharpInlineAnnotation: FSharp.Compiler.Symbols.FSharpInlineAnnotation get_AggressiveInline() FSharp.Compiler.Symbols.FSharpInlineAnnotation: FSharp.Compiler.Symbols.FSharpInlineAnnotation get_AlwaysInline() FSharp.Compiler.Symbols.FSharpInlineAnnotation: FSharp.Compiler.Symbols.FSharpInlineAnnotation get_NeverInline() FSharp.Compiler.Symbols.FSharpInlineAnnotation: FSharp.Compiler.Symbols.FSharpInlineAnnotation get_OptionalInline() -FSharp.Compiler.Symbols.FSharpInlineAnnotation: FSharp.Compiler.Symbols.FSharpInlineAnnotation get_PseudoValue() FSharp.Compiler.Symbols.FSharpInlineAnnotation: FSharp.Compiler.Symbols.FSharpInlineAnnotation+Tags FSharp.Compiler.Symbols.FSharpInlineAnnotation: Int32 CompareTo(FSharp.Compiler.Symbols.FSharpInlineAnnotation) FSharp.Compiler.Symbols.FSharpInlineAnnotation: Int32 CompareTo(System.Object) @@ -5193,24 +5188,29 @@ FSharp.Compiler.Syntax.DebugPointAtFor: Int32 Tag FSharp.Compiler.Syntax.DebugPointAtFor: Int32 get_Tag() FSharp.Compiler.Syntax.DebugPointAtFor: System.String ToString() FSharp.Compiler.Syntax.DebugPointAtSequential -FSharp.Compiler.Syntax.DebugPointAtSequential+Tags: Int32 Both -FSharp.Compiler.Syntax.DebugPointAtSequential+Tags: Int32 ExprOnly -FSharp.Compiler.Syntax.DebugPointAtSequential+Tags: Int32 StmtOnly +FSharp.Compiler.Syntax.DebugPointAtSequential+Tags: Int32 SuppressBoth +FSharp.Compiler.Syntax.DebugPointAtSequential+Tags: Int32 SuppressExpr +FSharp.Compiler.Syntax.DebugPointAtSequential+Tags: Int32 SuppressNeither +FSharp.Compiler.Syntax.DebugPointAtSequential+Tags: Int32 SuppressStmt FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean Equals(FSharp.Compiler.Syntax.DebugPointAtSequential) FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean Equals(System.Object) FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean IsBoth -FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean IsExprOnly -FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean IsStmtOnly -FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean get_IsBoth() -FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean get_IsExprOnly() -FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean get_IsStmtOnly() -FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential Both -FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential ExprOnly -FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential StmtOnly -FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential get_Both() -FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential get_ExprOnly() -FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential get_StmtOnly() +FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean IsSuppressBoth +FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean IsSuppressExpr +FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean IsSuppressNeither +FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean IsSuppressStmt +FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean get_IsSuppressBoth() +FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean get_IsSuppressExpr() +FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean get_IsSuppressNeither() +FSharp.Compiler.Syntax.DebugPointAtSequential: Boolean get_IsSuppressStmt() +FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential SuppressBoth +FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential SuppressExpr +FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential SuppressNeither +FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential SuppressStmt +FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential get_SuppressBoth() +FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential get_SuppressExpr() +FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential get_SuppressNeither() +FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential get_SuppressStmt() FSharp.Compiler.Syntax.DebugPointAtSequential: FSharp.Compiler.Syntax.DebugPointAtSequential+Tags FSharp.Compiler.Syntax.DebugPointAtSequential: Int32 CompareTo(FSharp.Compiler.Syntax.DebugPointAtSequential) FSharp.Compiler.Syntax.DebugPointAtSequential: Int32 CompareTo(System.Object) @@ -5680,7 +5680,9 @@ FSharp.Compiler.Syntax.SynArgInfo: Boolean optional FSharp.Compiler.Syntax.SynArgInfo: FSharp.Compiler.Syntax.SynArgInfo NewSynArgInfo(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], Boolean, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident]) FSharp.Compiler.Syntax.SynArgInfo: Int32 Tag FSharp.Compiler.Syntax.SynArgInfo: Int32 get_Tag() +FSharp.Compiler.Syntax.SynArgInfo: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] Attributes FSharp.Compiler.Syntax.SynArgInfo: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] attributes +FSharp.Compiler.Syntax.SynArgInfo: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] get_Attributes() FSharp.Compiler.Syntax.SynArgInfo: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] get_attributes() FSharp.Compiler.Syntax.SynArgInfo: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident] Ident FSharp.Compiler.Syntax.SynArgInfo: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.Ident] get_Ident() @@ -5729,12 +5731,12 @@ FSharp.Compiler.Syntax.SynAttributeList: Microsoft.FSharp.Collections.FSharpList FSharp.Compiler.Syntax.SynAttributeList: System.String ToString() FSharp.Compiler.Syntax.SynAttributeList: Void .ctor(Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttribute], FSharp.Compiler.Text.Range) FSharp.Compiler.Syntax.SynBinding +FSharp.Compiler.Syntax.SynBinding: Boolean get_isInline() FSharp.Compiler.Syntax.SynBinding: Boolean get_isMutable() -FSharp.Compiler.Syntax.SynBinding: Boolean get_mustInline() +FSharp.Compiler.Syntax.SynBinding: Boolean isInline FSharp.Compiler.Syntax.SynBinding: Boolean isMutable -FSharp.Compiler.Syntax.SynBinding: Boolean mustInline -FSharp.Compiler.Syntax.SynBinding: FSharp.Compiler.Syntax.DebugPointAtBinding get_seqPoint() -FSharp.Compiler.Syntax.SynBinding: FSharp.Compiler.Syntax.DebugPointAtBinding seqPoint +FSharp.Compiler.Syntax.SynBinding: FSharp.Compiler.Syntax.DebugPointAtBinding debugPoint +FSharp.Compiler.Syntax.SynBinding: FSharp.Compiler.Syntax.DebugPointAtBinding get_debugPoint() FSharp.Compiler.Syntax.SynBinding: FSharp.Compiler.Syntax.SynBinding NewSynBinding(Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess], FSharp.Compiler.Syntax.SynBindingKind, Boolean, Boolean, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList], FSharp.Compiler.Xml.PreXmlDoc, FSharp.Compiler.Syntax.SynValData, FSharp.Compiler.Syntax.SynPat, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynBindingReturnInfo], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.DebugPointAtBinding) FSharp.Compiler.Syntax.SynBinding: FSharp.Compiler.Syntax.SynBindingKind get_kind() FSharp.Compiler.Syntax.SynBinding: FSharp.Compiler.Syntax.SynBindingKind kind @@ -6215,8 +6217,8 @@ FSharp.Compiler.Syntax.SynExpr+Fixed: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+Fixed: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynExpr+For: Boolean direction FSharp.Compiler.Syntax.SynExpr+For: Boolean get_direction() -FSharp.Compiler.Syntax.SynExpr+For: FSharp.Compiler.Syntax.DebugPointAtFor forSeqPoint -FSharp.Compiler.Syntax.SynExpr+For: FSharp.Compiler.Syntax.DebugPointAtFor get_forSeqPoint() +FSharp.Compiler.Syntax.SynExpr+For: FSharp.Compiler.Syntax.DebugPointAtFor forDebugPoint +FSharp.Compiler.Syntax.SynExpr+For: FSharp.Compiler.Syntax.DebugPointAtFor get_forDebugPoint() FSharp.Compiler.Syntax.SynExpr+For: FSharp.Compiler.Syntax.Ident get_ident() FSharp.Compiler.Syntax.SynExpr+For: FSharp.Compiler.Syntax.Ident ident FSharp.Compiler.Syntax.SynExpr+For: FSharp.Compiler.Syntax.SynExpr doBody @@ -6229,8 +6231,8 @@ FSharp.Compiler.Syntax.SynExpr+For: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+For: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynExpr+ForEach: Boolean get_isFromSource() FSharp.Compiler.Syntax.SynExpr+ForEach: Boolean isFromSource -FSharp.Compiler.Syntax.SynExpr+ForEach: FSharp.Compiler.Syntax.DebugPointAtFor forSeqPoint -FSharp.Compiler.Syntax.SynExpr+ForEach: FSharp.Compiler.Syntax.DebugPointAtFor get_forSeqPoint() +FSharp.Compiler.Syntax.SynExpr+ForEach: FSharp.Compiler.Syntax.DebugPointAtFor forDebugPoint +FSharp.Compiler.Syntax.SynExpr+ForEach: FSharp.Compiler.Syntax.DebugPointAtFor get_forDebugPoint() FSharp.Compiler.Syntax.SynExpr+ForEach: FSharp.Compiler.Syntax.SeqExprOnly get_seqExprOnly() FSharp.Compiler.Syntax.SynExpr+ForEach: FSharp.Compiler.Syntax.SeqExprOnly seqExprOnly FSharp.Compiler.Syntax.SynExpr+ForEach: FSharp.Compiler.Syntax.SynExpr bodyExpr @@ -6315,8 +6317,8 @@ FSharp.Compiler.Syntax.SynExpr+LetOrUseBang: Boolean get_isFromSource() FSharp.Compiler.Syntax.SynExpr+LetOrUseBang: Boolean get_isUse() FSharp.Compiler.Syntax.SynExpr+LetOrUseBang: Boolean isFromSource FSharp.Compiler.Syntax.SynExpr+LetOrUseBang: Boolean isUse -FSharp.Compiler.Syntax.SynExpr+LetOrUseBang: FSharp.Compiler.Syntax.DebugPointAtBinding bindSeqPoint -FSharp.Compiler.Syntax.SynExpr+LetOrUseBang: FSharp.Compiler.Syntax.DebugPointAtBinding get_bindSeqPoint() +FSharp.Compiler.Syntax.SynExpr+LetOrUseBang: FSharp.Compiler.Syntax.DebugPointAtBinding bindDebugPoint +FSharp.Compiler.Syntax.SynExpr+LetOrUseBang: FSharp.Compiler.Syntax.DebugPointAtBinding get_bindDebugPoint() FSharp.Compiler.Syntax.SynExpr+LetOrUseBang: FSharp.Compiler.Syntax.SynExpr body FSharp.Compiler.Syntax.SynExpr+LetOrUseBang: FSharp.Compiler.Syntax.SynExpr get_body() FSharp.Compiler.Syntax.SynExpr+LetOrUseBang: FSharp.Compiler.Syntax.SynExpr get_rhs() @@ -6377,16 +6379,16 @@ FSharp.Compiler.Syntax.SynExpr+LongIdentSet: FSharp.Compiler.Syntax.SynExpr expr FSharp.Compiler.Syntax.SynExpr+LongIdentSet: FSharp.Compiler.Syntax.SynExpr get_expr() FSharp.Compiler.Syntax.SynExpr+LongIdentSet: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+LongIdentSet: FSharp.Compiler.Text.Range range -FSharp.Compiler.Syntax.SynExpr+Match: FSharp.Compiler.Syntax.DebugPointAtBinding get_matchSeqPoint() -FSharp.Compiler.Syntax.SynExpr+Match: FSharp.Compiler.Syntax.DebugPointAtBinding matchSeqPoint +FSharp.Compiler.Syntax.SynExpr+Match: FSharp.Compiler.Syntax.DebugPointAtBinding get_matchDebugPoint() +FSharp.Compiler.Syntax.SynExpr+Match: FSharp.Compiler.Syntax.DebugPointAtBinding matchDebugPoint FSharp.Compiler.Syntax.SynExpr+Match: FSharp.Compiler.Syntax.SynExpr expr FSharp.Compiler.Syntax.SynExpr+Match: FSharp.Compiler.Syntax.SynExpr get_expr() FSharp.Compiler.Syntax.SynExpr+Match: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+Match: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynExpr+Match: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMatchClause] clauses FSharp.Compiler.Syntax.SynExpr+Match: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMatchClause] get_clauses() -FSharp.Compiler.Syntax.SynExpr+MatchBang: FSharp.Compiler.Syntax.DebugPointAtBinding get_matchSeqPoint() -FSharp.Compiler.Syntax.SynExpr+MatchBang: FSharp.Compiler.Syntax.DebugPointAtBinding matchSeqPoint +FSharp.Compiler.Syntax.SynExpr+MatchBang: FSharp.Compiler.Syntax.DebugPointAtBinding get_matchDebugPoint() +FSharp.Compiler.Syntax.SynExpr+MatchBang: FSharp.Compiler.Syntax.DebugPointAtBinding matchDebugPoint FSharp.Compiler.Syntax.SynExpr+MatchBang: FSharp.Compiler.Syntax.SynExpr expr FSharp.Compiler.Syntax.SynExpr+MatchBang: FSharp.Compiler.Syntax.SynExpr get_expr() FSharp.Compiler.Syntax.SynExpr+MatchBang: FSharp.Compiler.Text.Range get_range() @@ -6395,8 +6397,8 @@ FSharp.Compiler.Syntax.SynExpr+MatchBang: Microsoft.FSharp.Collections.FSharpLis FSharp.Compiler.Syntax.SynExpr+MatchBang: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynMatchClause] get_clauses() FSharp.Compiler.Syntax.SynExpr+MatchLambda: Boolean get_isExnMatch() FSharp.Compiler.Syntax.SynExpr+MatchLambda: Boolean isExnMatch -FSharp.Compiler.Syntax.SynExpr+MatchLambda: FSharp.Compiler.Syntax.DebugPointAtBinding get_matchSeqPoint() -FSharp.Compiler.Syntax.SynExpr+MatchLambda: FSharp.Compiler.Syntax.DebugPointAtBinding matchSeqPoint +FSharp.Compiler.Syntax.SynExpr+MatchLambda: FSharp.Compiler.Syntax.DebugPointAtBinding get_matchDebugPoint() +FSharp.Compiler.Syntax.SynExpr+MatchLambda: FSharp.Compiler.Syntax.DebugPointAtBinding matchDebugPoint FSharp.Compiler.Syntax.SynExpr+MatchLambda: FSharp.Compiler.Text.Range get_keywordRange() FSharp.Compiler.Syntax.SynExpr+MatchLambda: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+MatchLambda: FSharp.Compiler.Text.Range keywordRange @@ -6461,16 +6463,16 @@ FSharp.Compiler.Syntax.SynExpr+Record: Microsoft.FSharp.Core.FSharpOption`1[Syst FSharp.Compiler.Syntax.SynExpr+Record: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`5[FSharp.Compiler.Syntax.SynType,FSharp.Compiler.Syntax.SynExpr,FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`2[FSharp.Compiler.Text.Range,Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Text.Position]]],FSharp.Compiler.Text.Range]] get_baseInfo() FSharp.Compiler.Syntax.SynExpr+Sequential: Boolean get_isTrueSeq() FSharp.Compiler.Syntax.SynExpr+Sequential: Boolean isTrueSeq -FSharp.Compiler.Syntax.SynExpr+Sequential: FSharp.Compiler.Syntax.DebugPointAtSequential get_seqPoint() -FSharp.Compiler.Syntax.SynExpr+Sequential: FSharp.Compiler.Syntax.DebugPointAtSequential seqPoint +FSharp.Compiler.Syntax.SynExpr+Sequential: FSharp.Compiler.Syntax.DebugPointAtSequential debugPoint +FSharp.Compiler.Syntax.SynExpr+Sequential: FSharp.Compiler.Syntax.DebugPointAtSequential get_debugPoint() FSharp.Compiler.Syntax.SynExpr+Sequential: FSharp.Compiler.Syntax.SynExpr expr1 FSharp.Compiler.Syntax.SynExpr+Sequential: FSharp.Compiler.Syntax.SynExpr expr2 FSharp.Compiler.Syntax.SynExpr+Sequential: FSharp.Compiler.Syntax.SynExpr get_expr1() FSharp.Compiler.Syntax.SynExpr+Sequential: FSharp.Compiler.Syntax.SynExpr get_expr2() FSharp.Compiler.Syntax.SynExpr+Sequential: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+Sequential: FSharp.Compiler.Text.Range range -FSharp.Compiler.Syntax.SynExpr+SequentialOrImplicitYield: FSharp.Compiler.Syntax.DebugPointAtSequential get_seqPoint() -FSharp.Compiler.Syntax.SynExpr+SequentialOrImplicitYield: FSharp.Compiler.Syntax.DebugPointAtSequential seqPoint +FSharp.Compiler.Syntax.SynExpr+SequentialOrImplicitYield: FSharp.Compiler.Syntax.DebugPointAtSequential debugPoint +FSharp.Compiler.Syntax.SynExpr+SequentialOrImplicitYield: FSharp.Compiler.Syntax.DebugPointAtSequential get_debugPoint() FSharp.Compiler.Syntax.SynExpr+SequentialOrImplicitYield: FSharp.Compiler.Syntax.SynExpr expr1 FSharp.Compiler.Syntax.SynExpr+SequentialOrImplicitYield: FSharp.Compiler.Syntax.SynExpr expr2 FSharp.Compiler.Syntax.SynExpr+SequentialOrImplicitYield: FSharp.Compiler.Syntax.SynExpr get_expr1() @@ -6556,20 +6558,20 @@ FSharp.Compiler.Syntax.SynExpr+TraitCall: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+TraitCall: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynExpr+TraitCall: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypar] get_supportTys() FSharp.Compiler.Syntax.SynExpr+TraitCall: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynTypar] supportTys -FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.DebugPointAtFinally finallySeqPoint -FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.DebugPointAtFinally get_finallySeqPoint() -FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.DebugPointAtTry get_trySeqPoint() -FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.DebugPointAtTry trySeqPoint +FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.DebugPointAtFinally finallyDebugPoint +FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.DebugPointAtFinally get_finallyDebugPoint() +FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.DebugPointAtTry get_tryDebugPoint() +FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.DebugPointAtTry tryDebugPoint FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.SynExpr finallyExpr FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.SynExpr get_finallyExpr() FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.SynExpr get_tryExpr() FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Syntax.SynExpr tryExpr FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+TryFinally: FSharp.Compiler.Text.Range range -FSharp.Compiler.Syntax.SynExpr+TryWith: FSharp.Compiler.Syntax.DebugPointAtTry get_trySeqPoint() -FSharp.Compiler.Syntax.SynExpr+TryWith: FSharp.Compiler.Syntax.DebugPointAtTry trySeqPoint -FSharp.Compiler.Syntax.SynExpr+TryWith: FSharp.Compiler.Syntax.DebugPointAtWith get_withSeqPoint() -FSharp.Compiler.Syntax.SynExpr+TryWith: FSharp.Compiler.Syntax.DebugPointAtWith withSeqPoint +FSharp.Compiler.Syntax.SynExpr+TryWith: FSharp.Compiler.Syntax.DebugPointAtTry get_tryDebugPoint() +FSharp.Compiler.Syntax.SynExpr+TryWith: FSharp.Compiler.Syntax.DebugPointAtTry tryDebugPoint +FSharp.Compiler.Syntax.SynExpr+TryWith: FSharp.Compiler.Syntax.DebugPointAtWith get_withDebugPoint() +FSharp.Compiler.Syntax.SynExpr+TryWith: FSharp.Compiler.Syntax.DebugPointAtWith withDebugPoint FSharp.Compiler.Syntax.SynExpr+TryWith: FSharp.Compiler.Syntax.SynExpr get_tryExpr() FSharp.Compiler.Syntax.SynExpr+TryWith: FSharp.Compiler.Syntax.SynExpr tryExpr FSharp.Compiler.Syntax.SynExpr+TryWith: FSharp.Compiler.Text.Range get_range() @@ -6620,8 +6622,8 @@ FSharp.Compiler.Syntax.SynExpr+Upcast: FSharp.Compiler.Syntax.SynType get_target FSharp.Compiler.Syntax.SynExpr+Upcast: FSharp.Compiler.Syntax.SynType targetType FSharp.Compiler.Syntax.SynExpr+Upcast: FSharp.Compiler.Text.Range get_range() FSharp.Compiler.Syntax.SynExpr+Upcast: FSharp.Compiler.Text.Range range -FSharp.Compiler.Syntax.SynExpr+While: FSharp.Compiler.Syntax.DebugPointAtWhile get_whileSeqPoint() -FSharp.Compiler.Syntax.SynExpr+While: FSharp.Compiler.Syntax.DebugPointAtWhile whileSeqPoint +FSharp.Compiler.Syntax.SynExpr+While: FSharp.Compiler.Syntax.DebugPointAtWhile get_whileDebugPoint() +FSharp.Compiler.Syntax.SynExpr+While: FSharp.Compiler.Syntax.DebugPointAtWhile whileDebugPoint FSharp.Compiler.Syntax.SynExpr+While: FSharp.Compiler.Syntax.SynExpr doExpr FSharp.Compiler.Syntax.SynExpr+While: FSharp.Compiler.Syntax.SynExpr get_doExpr() FSharp.Compiler.Syntax.SynExpr+While: FSharp.Compiler.Syntax.SynExpr get_whileExpr() @@ -6997,8 +6999,8 @@ FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 Tag FSharp.Compiler.Syntax.SynInterpolatedStringPart: Int32 get_Tag() FSharp.Compiler.Syntax.SynInterpolatedStringPart: System.String ToString() FSharp.Compiler.Syntax.SynMatchClause -FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointForTarget get_spInfo() -FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointForTarget spInfo +FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointForTarget debugPoint +FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.DebugPointForTarget get_debugPoint() FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.SynExpr get_resultExpr() FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.SynExpr resultExpr FSharp.Compiler.Syntax.SynMatchClause: FSharp.Compiler.Syntax.SynMatchClause NewSynMatchClause(FSharp.Compiler.Syntax.SynPat, Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynExpr], FSharp.Compiler.Syntax.SynExpr, FSharp.Compiler.Text.Range, FSharp.Compiler.Syntax.DebugPointForTarget) @@ -7357,8 +7359,8 @@ FSharp.Compiler.Syntax.SynModuleDecl+Attributes: FSharp.Compiler.Text.Range get_ FSharp.Compiler.Syntax.SynModuleDecl+Attributes: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynModuleDecl+Attributes: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] attributes FSharp.Compiler.Syntax.SynModuleDecl+Attributes: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] get_attributes() -FSharp.Compiler.Syntax.SynModuleDecl+DoExpr: FSharp.Compiler.Syntax.DebugPointAtBinding get_spInfo() -FSharp.Compiler.Syntax.SynModuleDecl+DoExpr: FSharp.Compiler.Syntax.DebugPointAtBinding spInfo +FSharp.Compiler.Syntax.SynModuleDecl+DoExpr: FSharp.Compiler.Syntax.DebugPointAtBinding debugPoint +FSharp.Compiler.Syntax.SynModuleDecl+DoExpr: FSharp.Compiler.Syntax.DebugPointAtBinding get_debugPoint() FSharp.Compiler.Syntax.SynModuleDecl+DoExpr: FSharp.Compiler.Syntax.SynExpr expr FSharp.Compiler.Syntax.SynModuleDecl+DoExpr: FSharp.Compiler.Syntax.SynExpr get_expr() FSharp.Compiler.Syntax.SynModuleDecl+DoExpr: FSharp.Compiler.Text.Range get_range() @@ -7711,8 +7713,8 @@ FSharp.Compiler.Syntax.SynPat+LongIdent: Microsoft.FSharp.Core.FSharpOption`1[FS FSharp.Compiler.Syntax.SynPat+LongIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynAccess] get_accessibility() FSharp.Compiler.Syntax.SynPat+LongIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynValTyparDecls] get_typarDecls() FSharp.Compiler.Syntax.SynPat+LongIdent: Microsoft.FSharp.Core.FSharpOption`1[FSharp.Compiler.Syntax.SynValTyparDecls] typarDecls -FSharp.Compiler.Syntax.SynPat+Named: Boolean get_isSelfIdentifier() -FSharp.Compiler.Syntax.SynPat+Named: Boolean isSelfIdentifier +FSharp.Compiler.Syntax.SynPat+Named: Boolean get_isThisVal() +FSharp.Compiler.Syntax.SynPat+Named: Boolean isThisVal FSharp.Compiler.Syntax.SynPat+Named: FSharp.Compiler.Syntax.Ident get_ident() FSharp.Compiler.Syntax.SynPat+Named: FSharp.Compiler.Syntax.Ident ident FSharp.Compiler.Syntax.SynPat+Named: FSharp.Compiler.Text.Range get_range() @@ -7910,11 +7912,11 @@ FSharp.Compiler.Syntax.SynSimplePat+Attrib: FSharp.Compiler.Text.Range range FSharp.Compiler.Syntax.SynSimplePat+Attrib: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] attributes FSharp.Compiler.Syntax.SynSimplePat+Attrib: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.Syntax.SynAttributeList] get_attributes() FSharp.Compiler.Syntax.SynSimplePat+Id: Boolean get_isCompilerGenerated() -FSharp.Compiler.Syntax.SynSimplePat+Id: Boolean get_isOptArg() -FSharp.Compiler.Syntax.SynSimplePat+Id: Boolean get_isThisVar() +FSharp.Compiler.Syntax.SynSimplePat+Id: Boolean get_isOptional() +FSharp.Compiler.Syntax.SynSimplePat+Id: Boolean get_isThisVal() FSharp.Compiler.Syntax.SynSimplePat+Id: Boolean isCompilerGenerated -FSharp.Compiler.Syntax.SynSimplePat+Id: Boolean isOptArg -FSharp.Compiler.Syntax.SynSimplePat+Id: Boolean isThisVar +FSharp.Compiler.Syntax.SynSimplePat+Id: Boolean isOptional +FSharp.Compiler.Syntax.SynSimplePat+Id: Boolean isThisVal FSharp.Compiler.Syntax.SynSimplePat+Id: FSharp.Compiler.Syntax.Ident get_ident() FSharp.Compiler.Syntax.SynSimplePat+Id: FSharp.Compiler.Syntax.Ident ident FSharp.Compiler.Syntax.SynSimplePat+Id: FSharp.Compiler.Text.Range get_range() diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj b/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj index c8563881b32..aa39265d2a0 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj +++ b/tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj @@ -3,7 +3,7 @@ - net472;net5.0 + net5.0;net472 net5.0 Library @@ -80,6 +80,8 @@ + + diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/CreateComparersRegression.fsx b/tests/FSharp.Core.UnitTests/FSharp.Core/CreateComparersRegression.fsx index 88feb45bdc9..9066e2a19f6 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/CreateComparersRegression.fsx +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/CreateComparersRegression.fsx @@ -3,4 +3,4 @@ #r @"..\..\..\..\Release\net40\bin\FSharp.Core.UnitTests.dll" -FSharp.Core.UnitTests.ComparersRegression.createData () \ No newline at end of file +FSharp.Core.UnitTests.ComparersRegression.createData () diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs index 57347f90f6f..982342dae06 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule2.fs @@ -850,7 +850,7 @@ type ArrayModule2() = // float32 array let floatArray: string[] = [| "1.2";"3.5";"6.7" |] let resultFloat = Array.sumBy float32 floatArray - if resultFloat <> 11.4f then Assert.Fail() + if abs (resultFloat - 11.4f) > 0.00000001f then Assert.Fail() // double array let doubleArray: System.Double[] = [| 1.0;8.0 |] diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Tasks.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Tasks.fs new file mode 100644 index 00000000000..fec401e7082 --- /dev/null +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/Tasks.fs @@ -0,0 +1,1325 @@ +// Tests for TaskBuilder.fs +// +// Written in 2016 by Robert Peele (humbobst@gmail.com) +// +// To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights +// to this software to the public domain worldwide. This software is distributed without any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication along with this software. +// If not, see . + + +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +// Various tests for the: +// Microsoft.FSharp.Control.Async type + +namespace FSharp.Core.UnitTests.Control.Tasks + +open System +open System.Collections +open System.Collections.Generic +open System.Diagnostics +open System.Threading +open System.Threading.Tasks +open Microsoft.FSharp.Control +#if STANDALONE +[] +type FactAttribute() = inherit Attribute() +#else +open Xunit +#endif + + +type ITaskThing = + abstract member Taskify : 'a option -> 'a Task + +#if NETCOREAPP +type SupportBothDisposables() = + let mutable called = false + interface IAsyncDisposable with + member __.DisposeAsync() = + task { + System.Console.WriteLine "incrementing" + called <- true } + |> ValueTask + interface IDisposable with + member __.Dispose() = failwith "dispose" + member x.Disposed = called +#endif +type SmokeTestsForCompilation() = + + [] + member __.tinyTask() = + task { + return 1 + } + |> fun t -> + t.Wait() + if t.Result <> 1 then failwith "failed" + + [] + member __.tbind() = + task { + let! x = Task.FromResult(1) + return 1 + x + } + |> fun t -> + t.Wait() + if t.Result <> 2 then failwith "failed" + + [] + member __.tnested() = + task { + let! x = task { return 1 } + return x + } + |> fun t -> + t.Wait() + if t.Result <> 1 then failwith "failed" + + [] + member __.tcatch0() = + task { + try + return 1 + with e -> + return 2 + } + |> fun t -> + t.Wait() + if t.Result <> 1 then failwith "failed" + + [] + member __.tcatch1() = + task { + try + let! x = Task.FromResult 1 + return x + with e -> + return 2 + } + |> fun t -> + t.Wait() + if t.Result <> 1 then failwith "failed" + + + [] + member __.t3() = + let t2() = + task { + System.Console.WriteLine("hello") + return 1 + } + task { + System.Console.WriteLine("hello") + let! x = t2() + System.Console.WriteLine("world") + return 1 + x + } + |> fun t -> + t.Wait() + if t.Result <> 2 then failwith "failed" + + [] + member __.t3b() = + task { + System.Console.WriteLine("hello") + let! x = Task.FromResult(1) + System.Console.WriteLine("world") + return 1 + x + } + |> fun t -> + t.Wait() + if t.Result <> 2 then failwith "failed" + + [] + member __.t3c() = + task { + System.Console.WriteLine("hello") + do! Task.Delay(100) + System.Console.WriteLine("world") + return 1 + } + |> fun t -> + t.Wait() + if t.Result <> 1 then failwith "failed" + + [] + // This tests an exception match + member __.t67() = + task { + try + do! Task.Delay(0) + with + | :? ArgumentException -> + () + | _ -> + () + } + |> fun t -> + t.Wait() + if t.Result <> () then failwith "failed" + + [] + // This tests compiling an incomplete exception match + member __.t68() = + task { + try + do! Task.Delay(0) + with + | :? ArgumentException -> + () + } + |> fun t -> + t.Wait() + if t.Result <> () then failwith "failed" + + [] + member __.testCompileAsyncWhileLoop() = + task { + let mutable i = 0 + while i < 5 do + i <- i + 1 + do! Task.Yield() + return i + } + |> fun t -> + t.Wait() + if t.Result <> 5 then failwith "failed" + + +exception TestException of string + +[] +module Helpers = + let BIG = 10 + // let BIG = 10000 + let require x msg = if not x then failwith msg + let failtest str = raise (TestException str) + +type Basics() = + [] + member __.testShortCircuitResult() = + printfn "Running testShortCircuitResult..." + let t = + task { + let! x = Task.FromResult(1) + let! y = Task.FromResult(2) + return x + y + } + require t.IsCompleted "didn't short-circuit already completed tasks" + printfn "t.Result = %A" t.Result + require (t.Result = 3) "wrong result" + + [] + member __.testDelay() = + printfn "Running testDelay..." + let mutable x = 0 + let t = + task { + do! Task.Delay(50) + x <- x + 1 + } + printfn "task created and first step run...." + require (x = 0) "task already ran" + printfn "waiting...." + t.Wait() + + [] + member __.testNoDelay() = + printfn "Running testNoDelay..." + let mutable x = 0 + let t = + task { + x <- x + 1 + do! Task.Delay(5) + x <- x + 1 + } + require (x = 1) "first part didn't run yet" + t.Wait() + + [] + member __.testNonBlocking() = + printfn "Running testNonBlocking..." + let sw = Stopwatch() + sw.Start() + let t = + task { + do! Task.Yield() + Thread.Sleep(100) + } + sw.Stop() + require (sw.ElapsedMilliseconds < 50L) "sleep blocked caller" + t.Wait() + + [] + member __.testCatching1() = + printfn "Running testCatching1..." + let mutable x = 0 + let mutable y = 0 + let t = + task { + try + do! Task.Delay(0) + failtest "hello" + x <- 1 + do! Task.Delay(100) + with + | TestException msg -> + require (msg = "hello") "message tampered" + | _ -> + require false "other exn type" + require false "other exn type" + y <- 1 + } + t.Wait() + require (y = 1) "bailed after exn" + require (x = 0) "ran past failure" + + [] + member __.testCatching2() = + printfn "Running testCatching2..." + let mutable x = 0 + let mutable y = 0 + let t = + task { + try + do! Task.Yield() // can't skip through this + failtest "hello" + x <- 1 + do! Task.Delay(100) + with + | TestException msg -> + require (msg = "hello") "message tampered" + | _ -> + require false "other exn type" + y <- 1 + } + t.Wait() + require (y = 1) "bailed after exn" + require (x = 0) "ran past failure" + + [] + member __.testNestedCatching() = + printfn "Running testNestedCatching..." + let mutable counter = 1 + let mutable caughtInner = 0 + let mutable caughtOuter = 0 + let t1() = + task { + try + do! Task.Yield() + failtest "hello" + with + | TestException msg as exn -> + caughtInner <- counter + counter <- counter + 1 + raise exn + } + let t2 = + task { + try + do! t1() + with + | TestException msg as exn -> + caughtOuter <- counter + raise exn + | e -> + require false (sprintf "invalid msg type %s" e.Message) + } + try + t2.Wait() + require false "ran past failed task wait" + with + | :? AggregateException as exn -> + require (exn.InnerExceptions.Count = 1) "more than 1 exn" + require (caughtInner = 1) "didn't catch inner" + require (caughtOuter = 2) "didn't catch outer" + + [] + member __.testWhileLoopSync() = + printfn "Running testWhileLoopSync..." + let t = + task { + let mutable i = 0 + while i < 10 do + i <- i + 1 + return i + } + //t.Wait() no wait required for sync loop + require (t.IsCompleted) "didn't do sync while loop properly - not completed" + require (t.Result = 10) "didn't do sync while loop properly - wrong result" + + [] + member __.testWhileLoopAsyncZeroIteration() = + printfn "Running testWhileLoopAsyncZeroIteration..." + for i in 1 .. 5 do + let t = + task { + let mutable i = 0 + while i < 0 do + i <- i + 1 + do! Task.Yield() + return i + } + t.Wait() + require (t.Result = 0) "didn't do while loop properly" + + [] + member __.testWhileLoopAsyncOneIteration() = + printfn "Running testWhileLoopAsyncOneIteration..." + for i in 1 .. 5 do + let t = + task { + let mutable i = 0 + while i < 1 do + i <- i + 1 + do! Task.Yield() + return i + } + t.Wait() + require (t.Result = 1) "didn't do while loop properly" + + [] + member __.testWhileLoopAsync() = + printfn "Running testWhileLoopAsync..." + for i in 1 .. 5 do + let t = + task { + let mutable i = 0 + while i < 10 do + i <- i + 1 + do! Task.Yield() + return i + } + t.Wait() + require (t.Result = 10) "didn't do while loop properly" + + [] + member __.testTryFinallyHappyPath() = + printfn "Running testTryFinallyHappyPath..." + for i in 1 .. 5 do + let mutable ran = false + let t = + task { + try + require (not ran) "ran way early" + do! Task.Delay(100) + require (not ran) "ran kinda early" + finally + ran <- true + } + t.Wait() + require ran "never ran" + [] + member __.testTryFinallySadPath() = + printfn "Running testTryFinallySadPath..." + for i in 1 .. 5 do + let mutable ran = false + let t = + task { + try + require (not ran) "ran way early" + do! Task.Delay(100) + require (not ran) "ran kinda early" + failtest "uhoh" + finally + ran <- true + } + try + t.Wait() + with + | _ -> () + require ran "never ran" + + [] + member __.testTryFinallyCaught() = + printfn "Running testTryFinallyCaught..." + for i in 1 .. 5 do + let mutable ran = false + let t = + task { + try + try + require (not ran) "ran way early" + do! Task.Delay(100) + require (not ran) "ran kinda early" + failtest "uhoh" + finally + ran <- true + return 1 + with + | _ -> return 2 + } + require (t.Result = 2) "wrong return" + require ran "never ran" + + [] + member __.testUsing() = + printfn "Running testUsing..." + for i in 1 .. 5 do + let mutable disposed = false + let t = + task { + use d = { new IDisposable with member __.Dispose() = disposed <- true } + require (not disposed) "disposed way early" + do! Task.Delay(100) + require (not disposed) "disposed kinda early" + } + t.Wait() + require disposed "never disposed B" + +#if NETCOREAPP + [] + member __.testUsingAsyncDisposableSync() = + printfn "Running testUsingAsyncDisposableSync..." + for i in 1 .. 5 do + let mutable disposed = 0 + let t = + task { + use d = + { new IAsyncDisposable with + member __.DisposeAsync() = + task { + System.Console.WriteLine "incrementing" + disposed <- disposed + 1 } + |> ValueTask + } + require (disposed = 0) "disposed way early" + System.Console.WriteLine "delaying" + do! Task.Delay(100) + System.Console.WriteLine "testing" + require (disposed = 0) "disposed kinda early" + } + t.Wait() + require (disposed >= 1) "never disposed B" + require (disposed <= 1) "too many dispose on B" + + [] + member __.testUsingAsyncDisposableAsync() = + printfn "Running testUsingAsyncDisposableAsync..." + for i in 1 .. 5 do + let mutable disposed = 0 + let t = + task { + use d = + { new IAsyncDisposable with + member __.DisposeAsync() = + task { + do! Task.Delay(10) + disposed <- disposed + 1 + } + |> ValueTask + } + require (disposed = 0) "disposed way early" + do! Task.Delay(100) + require (disposed = 0) "disposed kinda early" + } + t.Wait() + require (disposed >= 1) "never disposed B" + require (disposed <= 1) "too many dispose on B" + + [] + member __.testUsingAsyncDisposableExnAsync() = + printfn "Running testUsingAsyncDisposableExnAsync..." + for i in 1 .. 5 do + let mutable disposed = 0 + let t = + task { + use d = + { new IAsyncDisposable with + member __.DisposeAsync() = + task { + do! Task.Delay(10) + disposed <- disposed + 1 + } + |> ValueTask + } + require (disposed = 0) "disposed way early" + failtest "oops" + + } + try t.Wait() + with | :? AggregateException -> + require (disposed >= 1) "never disposed B" + require (disposed <= 1) "too many dispose on B" + + [] + member __.testUsingAsyncDisposableExnSync() = + printfn "Running testUsingAsyncDisposableExnSync..." + for i in 1 .. 5 do + let mutable disposed = 0 + let t = + task { + use d = + { new IAsyncDisposable with + member __.DisposeAsync() = + task { + disposed <- disposed + 1 + do! Task.Delay(10) + } + |> ValueTask + } + require (disposed = 0) "disposed way early" + failtest "oops" + + } + try t.Wait() + with | :? AggregateException -> + require (disposed >= 1) "never disposed B" + require (disposed <= 1) "too many dispose on B" + + [] + member __.testUsingAsyncDisposableDelayExnSync() = + printfn "Running testUsingAsyncDisposableDelayExnSync..." + for i in 1 .. 5 do + let mutable disposed = 0 + let t = + task { + use d = + { new IAsyncDisposable with + member __.DisposeAsync() = + task { + disposed <- disposed + 1 + do! Task.Delay(10) + } + |> ValueTask + } + require (disposed = 0) "disposed way early" + do! Task.Delay(10) + require (disposed = 0) "disposed kind of early" + failtest "oops" + + } + try t.Wait() + with | :? AggregateException -> + require (disposed >= 1) "never disposed B" + require (disposed <= 1) "too many dispose on B" + + [] + // Test use! resolves + member __.testUsingBindAsyncDisposableSync() = + printfn "Running testUsingBindAsyncDisposableSync..." + for i in 1 .. 5 do + let mutable disposed = 0 + let t = + task { + use! d = + task { + do! Task.Delay(10) + return + { new IAsyncDisposable with + member __.DisposeAsync() = + task { + System.Console.WriteLine "incrementing" + disposed <- disposed + 1 } + |> ValueTask + } + } + require (disposed = 0) "disposed way early" + System.Console.WriteLine "delaying" + do! Task.Delay(100) + System.Console.WriteLine "testing" + require (disposed = 0) "disposed kinda early" + } + t.Wait() + require (disposed >= 1) "never disposed B" + require (disposed <= 1) "too many dispose on B" + + [] + member __.testUsingAsyncDisposableSyncSupportingBothDisposables() = + printfn "Running testUsingAsyncDisposableSyncSupportingBothDisposables..." + for i in 1 .. 5 do + let disp = new SupportBothDisposables() + let t = + task { + use d = disp + require (not disp.Disposed) "disposed way early" + System.Console.WriteLine "delaying" + do! Task.Delay(100) + System.Console.WriteLine "testing" + require (not disp.Disposed) "disposed kinda early" + } + t.Wait() + require disp.Disposed "never disposed B" +#endif + + [] + member __.testUsingFromTask() = + printfn "Running testUsingFromTask..." + let mutable disposedInner = false + let mutable disposed = false + let t = + task { + use! d = + task { + do! Task.Delay(50) + use i = { new IDisposable with member __.Dispose() = disposedInner <- true } + require (not disposed && not disposedInner) "disposed inner early" + return { new IDisposable with member __.Dispose() = disposed <- true } + } + require disposedInner "did not dispose inner after task completion" + require (not disposed) "disposed way early" + do! Task.Delay(50) + require (not disposed) "disposed kinda early" + } + t.Wait() + require disposed "never disposed C" + + [] + member __.testUsingSadPath() = + printfn "Running testUsingSadPath..." + let mutable disposedInner = false + let mutable disposed = false + let t = + task { + try + use! d = + task { + do! Task.Delay(50) + use i = { new IDisposable with member __.Dispose() = disposedInner <- true } + failtest "uhoh" + require (not disposed && not disposedInner) "disposed inner early" + return { new IDisposable with member __.Dispose() = disposed <- true } + } + () + with + | TestException msg -> + printfn "caught TestException" + require disposedInner "did not dispose inner after task completion" + require (not disposed) "disposed way early" + do! Task.Delay(50) + printfn "resumed after delay" + require (not disposed) "disposed kinda early" + } + t.Wait() + require (not disposed) "disposed thing that never should've existed" + + [] + member __.testForLoopA() = + printfn "Running testForLoopA..." + let list = ["a"; "b"; "c"] |> Seq.ofList + let t = + task { + printfn "entering loop..." + let mutable x = Unchecked.defaultof<_> + let e = list.GetEnumerator() + while e.MoveNext() do + x <- e.Current + printfn "x = %A" x + do! Task.Yield() + printfn "x = %A" x + } + t.Wait() + + [] + member __.testForLoopComplex() = + printfn "Running testForLoopComplex..." + let mutable disposed = false + let wrapList = + let raw = ["a"; "b"; "c"] |> Seq.ofList + let getEnumerator() = + let raw = raw.GetEnumerator() + { new IEnumerator with + member __.MoveNext() = + require (not disposed) "moved next after disposal" + raw.MoveNext() + member __.Current = + require (not disposed) "accessed current after disposal" + raw.Current + member __.Current = + require (not disposed) "accessed current (boxed) after disposal" + box raw.Current + member __.Dispose() = + require (not disposed) "disposed twice" + disposed <- true + raw.Dispose() + member __.Reset() = + require (not disposed) "reset after disposal" + raw.Reset() + } + { new IEnumerable with + member __.GetEnumerator() : IEnumerator = getEnumerator() + member __.GetEnumerator() : IEnumerator = upcast getEnumerator() + } + let t = + task { + let mutable index = 0 + do! Task.Yield() + printfn "entering loop..." + for x in wrapList do + printfn "x = %A, index = %d" x index + do! Task.Yield() + printfn "back from yield" + do! Task.Yield() + printfn "back from yield" + match index with + | 0 -> require (x = "a") "wrong first value" + | 1 -> require (x = "b") "wrong second value" + | 2 -> require (x = "c") "wrong third value" + | _ -> require false "iterated too far!" + index <- index + 1 + printfn "yield again" + do! Task.Yield() + printfn "yield again again" + do! Task.Yield() + printfn "looping again..." + do! Task.Yield() + return 1 + } + t.Wait() + require disposed "never disposed D" + require (t.Result = 1) "wrong result" + + [] + member __.testForLoopSadPath() = + printfn "Running testForLoopSadPath..." + for i in 1 .. 5 do + let wrapList = ["a"; "b"; "c"] + let t = + task { + let mutable index = 0 + do! Task.Yield() + for x in wrapList do + do! Task.Yield() + index <- index + 1 + return 1 + } + require (t.Result = 1) "wrong result" + + [] + member __.testForLoopSadPathComplex() = + printfn "Running testForLoopSadPathComplex..." + for i in 1 .. 5 do + let mutable disposed = false + let wrapList = + let raw = ["a"; "b"; "c"] |> Seq.ofList + let getEnumerator() = + let raw = raw.GetEnumerator() + { new IEnumerator with + member __.MoveNext() = + require (not disposed) "moved next after disposal" + raw.MoveNext() + member __.Current = + require (not disposed) "accessed current after disposal" + raw.Current + member __.Current = + require (not disposed) "accessed current (boxed) after disposal" + box raw.Current + member __.Dispose() = + require (not disposed) "disposed twice" + disposed <- true + raw.Dispose() + member __.Reset() = + require (not disposed) "reset after disposal" + raw.Reset() + } + { new IEnumerable with + member __.GetEnumerator() : IEnumerator = getEnumerator() + member __.GetEnumerator() : IEnumerator = upcast getEnumerator() + } + let mutable caught = false + let t = + task { + try + let mutable index = 0 + do! Task.Yield() + for x in wrapList do + do! Task.Yield() + match index with + | 0 -> require (x = "a") "wrong first value" + | _ -> failtest "uhoh" + index <- index + 1 + do! Task.Yield() + do! Task.Yield() + return 1 + with + | TestException "uhoh" -> + caught <- true + return 2 + } + require (t.Result = 2) "wrong result" + require caught "didn't catch exception" + require disposed "never disposed A" + + [] + member __.testExceptionAttachedToTaskWithoutAwait() = + for i in 1 .. 5 do + let mutable ranA = false + let mutable ranB = false + let t = + task { + ranA <- true + failtest "uhoh" + ranB <- true + } + require ranA "didn't run immediately" + require (not ranB) "ran past exception" + require (not (isNull t.Exception)) "didn't capture exception" + require (t.Exception.InnerExceptions.Count = 1) "captured more exceptions" + require (t.Exception.InnerException = TestException "uhoh") "wrong exception" + let mutable caught = false + let mutable ranCatcher = false + let catcher = + task { + try + ranCatcher <- true + let! result = t + return false + with + | TestException "uhoh" -> + caught <- true + return true + } + require ranCatcher "didn't run" + require catcher.Result "didn't catch" + require caught "didn't catch" + + [] + member __.testExceptionAttachedToTaskWithAwait() = + printfn "running testExceptionAttachedToTaskWithAwait" + for i in 1 .. 5 do + let mutable ranA = false + let mutable ranB = false + let t = + task { + ranA <- true + failtest "uhoh" + do! Task.Delay(100) + ranB <- true + } + require ranA "didn't run immediately" + require (not ranB) "ran past exception" + require (not (isNull t.Exception)) "didn't capture exception" + require (t.Exception.InnerExceptions.Count = 1) "captured more exceptions" + require (t.Exception.InnerException = TestException "uhoh") "wrong exception" + let mutable caught = false + let mutable ranCatcher = false + let catcher = + task { + try + ranCatcher <- true + let! result = t + return false + with + | TestException "uhoh" -> + caught <- true + return true + } + require ranCatcher "didn't run" + require catcher.Result "didn't catch" + require caught "didn't catch" + + [] + member __.testExceptionThrownInFinally() = + printfn "running testExceptionThrownInFinally" + for i in 1 .. 5 do + let mutable ranInitial = false + let mutable ranNext = false + let mutable ranFinally = 0 + let t = + task { + try + ranInitial <- true + do! Task.Yield() + Thread.Sleep(100) // shouldn't be blocking so we should get through to requires before this finishes + ranNext <- true + finally + ranFinally <- ranFinally + 1 + failtest "finally exn!" + } + require ranInitial "didn't run initial" + require (not ranNext) "ran next too early" + try + t.Wait() + require false "shouldn't get here" + with + | _ -> () + require ranNext "didn't run next" + require (ranFinally = 1) "didn't run finally exactly once" + + [] + member __.test2ndExceptionThrownInFinally() = + printfn "running test2ndExceptionThrownInFinally" + for i in 1 .. 5 do + let mutable ranInitial = false + let mutable ranNext = false + let mutable ranFinally = 0 + let t = + task { + try + ranInitial <- true + do! Task.Yield() + Thread.Sleep(100) // shouldn't be blocking so we should get through to requires before this finishes + ranNext <- true + failtest "uhoh" + finally + ranFinally <- ranFinally + 1 + failtest "2nd exn!" + } + require ranInitial "didn't run initial" + require (not ranNext) "ran next too early" + try + t.Wait() + require false "shouldn't get here" + with + | _ -> () + require ranNext "didn't run next" + require (ranFinally = 1) "didn't run finally exactly once" + + [] + member __.testFixedStackWhileLoop() = + printfn "running testFixedStackWhileLoop" + for i in 1 .. 100 do + let t = + task { + let mutable maxDepth = Nullable() + let mutable i = 0 + while i < BIG do + i <- i + 1 + do! Task.Yield() + if i % 100 = 0 then + let stackDepth = StackTrace().FrameCount + if maxDepth.HasValue && stackDepth > maxDepth.Value then + failwith "Stack depth increased!" + maxDepth <- Nullable(stackDepth) + return i + } + t.Wait() + require (t.Result = BIG) "didn't get to big number" + + [] + member __.testFixedStackForLoop() = + for i in 1 .. 100 do + printfn "running testFixedStackForLoop" + let mutable ran = false + let t = + task { + let mutable maxDepth = Nullable() + for i in Seq.init BIG id do + do! Task.Yield() + if i % 100 = 0 then + let stackDepth = StackTrace().FrameCount + if maxDepth.HasValue && stackDepth > maxDepth.Value then + failwith "Stack depth increased!" + maxDepth <- Nullable(stackDepth) + ran <- true + return () + } + t.Wait() + require ran "didn't run all" + + [] + member __.testTypeInference() = + let t1 : string Task = + task { + return "hello" + } + let t2 = + task { + let! s = t1 + return s.Length + } + t2.Wait() + + [] + member __.testNoStackOverflowWithImmediateResult() = + printfn "running testNoStackOverflowWithImmediateResult" + let longLoop = + task { + let mutable n = 0 + while n < BIG do + n <- n + 1 + return! Task.FromResult(()) + } + longLoop.Wait() + + [] + member __.testNoStackOverflowWithYieldResult() = + printfn "running testNoStackOverflowWithYieldResult" + let longLoop = + task { + let mutable n = 0 + while n < BIG do + let! _ = + task { + do! Task.Yield() + let! _ = Task.FromResult(0) + n <- n + 1 + } + n <- n + 1 + } + longLoop.Wait() + + [] + member __.testSmallTailRecursion() = + printfn "running testSmallTailRecursion" + let rec loop n = + task { + if n < 100 then + do! Task.Yield() + let! _ = Task.FromResult(0) + return! loop (n + 1) + else + return () + } + let shortLoop = + task { + return! loop 0 + } + shortLoop.Wait() + + [] + member __.testTryOverReturnFrom() = + printfn "running testTryOverReturnFrom" + let inner() = + task { + do! Task.Yield() + failtest "inner" + return 1 + } + let t = + task { + try + do! Task.Yield() + return! inner() + with + | TestException "inner" -> return 2 + } + require (t.Result = 2) "didn't catch" + + [] + member __.testTryFinallyOverReturnFromWithException() = + printfn "running testTryFinallyOverReturnFromWithException" + let inner() = + task { + do! Task.Yield() + failtest "inner" + return 1 + } + let mutable m = 0 + let t = + task { + try + do! Task.Yield() + return! inner() + finally + m <- 1 + } + try + t.Wait() + with + | :? AggregateException -> () + require (m = 1) "didn't run finally" + + [] + member __.testTryFinallyOverReturnFromWithoutException() = + printfn "running testTryFinallyOverReturnFromWithoutException" + let inner() = + task { + do! Task.Yield() + return 1 + } + let mutable m = 0 + let t = + task { + try + do! Task.Yield() + return! inner() + finally + m <- 1 + } + try + t.Wait() + with + | :? AggregateException -> () + require (m = 1) "didn't run finally" + + // no need to call this, we just want to check that it compiles w/o warnings + member __.testTrivialReturnCompiles (x : 'a) : 'a Task = + task { + do! Task.Yield() + return x + } + + // no need to call this, we just want to check that it compiles w/o warnings + member __.testTrivialTransformedReturnCompiles (x : 'a) (f : 'a -> 'b) : 'b Task = + task { + do! Task.Yield() + return f x + } + + [] + member __.testAsyncsMixedWithTasks() = + let t = + task { + do! Task.Delay(1) + do! Async.Sleep(1) + let! x = + async { + do! Async.Sleep(1) + return 5 + } + return! async { return x + 3 } + } + let result = t.Result + require (result = 8) "something weird happened" + + [] + // no need to call this, we just want to check that it compiles w/o warnings + member __.testDefaultInferenceForReturnFrom() = + let t = task { return Some "x" } + task { + let! r = t + if r = None then + return! failwithf "Could not find x" + else + return r + } + |> ignore + + [] + // no need to call this, just check that it compiles + member __.testCompilerInfersArgumentOfReturnFrom() = + task { + if true then return 1 + else return! failwith "" + } + |> ignore + +[] +type BasicsNotInParallel() = + + [] + member __.testTaskUsesSyncContext() = + printfn "Running testBackgroundTask..." + for i in 1 .. 5 do + let mutable ran = false + let mutable posted = false + let oldSyncContext = SynchronizationContext.Current + let syncContext = { new SynchronizationContext() with member _.Post(d,state) = posted <- true; d.Invoke(state) } + try + SynchronizationContext.SetSynchronizationContext syncContext + let tid = System.Threading.Thread.CurrentThread.ManagedThreadId + require (not (isNull SynchronizationContext.Current)) "need sync context non null on foreground thread A" + require (SynchronizationContext.Current = syncContext) "need sync context known on foreground thread A" + let t = + task { + let tid2 = System.Threading.Thread.CurrentThread.ManagedThreadId + require (not (isNull SynchronizationContext.Current)) "need sync context non null on foreground thread B" + require (SynchronizationContext.Current = syncContext) "need sync context known on foreground thread B" + require (tid = tid2) "expected synchronous start for task B2" + do! Task.Yield() + require (not (isNull SynchronizationContext.Current)) "need sync context non null on foreground thread C" + require (SynchronizationContext.Current = syncContext) "need sync context known on foreground thread C" + ran <- true + } + t.Wait() + require ran "never ran" + require posted "never posted" + finally + SynchronizationContext.SetSynchronizationContext oldSyncContext + + [] + member __.testBackgroundTaskEscapesSyncContext() = + printfn "Running testBackgroundTask..." + for i in 1 .. 5 do + let mutable ran = false + let mutable posted = false + let oldSyncContext = SynchronizationContext.Current + let syncContext = { new SynchronizationContext() with member _.Post(d,state) = posted <- true; d.Invoke(state) } + try + SynchronizationContext.SetSynchronizationContext syncContext + let t = + backgroundTask { + require (System.Threading.Thread.CurrentThread.IsThreadPoolThread) "expect to be on background thread" + ran <- true + } + t.Wait() + require ran "never ran" + require (not posted) "did not expect post to sync context" + finally + SynchronizationContext.SetSynchronizationContext oldSyncContext + + [] + member __.testBackgroundTaskStaysOnSameThreadIfAlreadyOnBackground() = + printfn "Running testBackgroundTask..." + for i in 1 .. 5 do + let mutable ran = false + let taskOuter = + Task.Run(fun () -> + let tid = System.Threading.Thread.CurrentThread.ManagedThreadId + // In case other thread pool activities have polluted this one, sigh + SynchronizationContext.SetSynchronizationContext null + require (System.Threading.Thread.CurrentThread.IsThreadPoolThread) "expected thread pool thread (1)" + let t = + backgroundTask { + require (System.Threading.Thread.CurrentThread.IsThreadPoolThread) "expected thread pool thread (2)" + let tid2 = System.Threading.Thread.CurrentThread.ManagedThreadId + require (tid = tid2) "expected synchronous starts when already on background thread" + do! Task.Delay(200) + ran <- true + } + t.Wait() + require ran "never ran") + taskOuter.Wait() + + +#if STANDALONE +module M = + [] + let main argv = + printfn "Running tests..." + try + Basics().testShortCircuitResult() + Basics().testDelay() + Basics().testNoDelay() + Basics().testNonBlocking() + + Basics().testCatching1() + Basics().testCatching2() + Basics().testNestedCatching() + Basics().testWhileLoopSync() + Basics().testWhileLoopAsyncZeroIteration() + Basics().testWhileLoopAsyncOneIteration() + Basics().testWhileLoopAsync() + Basics().testTryFinallyHappyPath() + Basics().testTryFinallySadPath() + Basics().testTryFinallyCaught() + Basics().testUsing() + Basics().testUsingFromTask() + Basics().testUsingSadPath() + Basics().testForLoopA() + Basics().testForLoopSadPath() + Basics().testForLoopSadPathComplex() + Basics().testExceptionAttachedToTaskWithoutAwait() + Basics().testExceptionAttachedToTaskWithAwait() + Basics().testExceptionThrownInFinally() + Basics().test2ndExceptionThrownInFinally() + Basics().testFixedStackWhileLoop() + Basics().testFixedStackForLoop() + Basics().testTypeInference() + Basics().testNoStackOverflowWithImmediateResult() + Basics().testNoStackOverflowWithYieldResult() + ////// we don't support TCO, so large tail recursions will stack overflow + ////// or at least use O(n) heap. but small ones should at least function OK. + //testSmallTailRecursion() + Basics().testTryOverReturnFrom() + Basics().testTryFinallyOverReturnFromWithException() + Basics().testTryFinallyOverReturnFromWithoutException() + Basics().testAsyncsMixedWithTasks() + printfn "Passed all tests!" + with exn -> + eprintfn "************************************" + eprintfn "Exception: %O" exn + printfn "Test failed... exiting..." + eprintfn "************************************" + exit 1 + + printfn "Tests passed ok..., sleeping a bit in case there are background delayed exceptions" + Thread.Sleep(500) + printfn "Exiting..." + //System.Console.ReadLine() + 0 +#endif diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/TasksDynamic.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/TasksDynamic.fs new file mode 100644 index 00000000000..72d62f1e567 --- /dev/null +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/TasksDynamic.fs @@ -0,0 +1,1399 @@ +// Tests for TaskBuilder.fs +// +// Written in 2016 by Robert Peele (humbobst@gmail.com) +// +// To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights +// to this software to the public domain worldwide. This software is distributed without any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication along with this software. +// If not, see . +// +// +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +// Various tests for the 'dynamic' implementation of the task type when state machine +// compilation fails. + +namespace FSharp.Core.UnitTests.Control.TasksDynamic + +#nowarn "1204" // construct only for use in compiled code +#nowarn "3511" // state machine not staticlly compilable - the one in 'Run' +open System +open System.Collections +open System.Collections.Generic +open System.Diagnostics +open System.Threading +open System.Threading.Tasks +open Microsoft.FSharp.Control +#if STANDALONE +[] +type FactAttribute() = inherit Attribute() +#else +open Xunit +open System.Runtime.CompilerServices + +#endif + +// Delegates to task, except 'Run' which is deliberately not inlined, hence no chance +// of static compilation of state machines. +type TaskBuilderDynamic() = + + [] + member _.Run(code) = task.Run(code) // warning 3511 is generated here: state machine not compilable + + member inline _.Delay f = task.Delay(f) + [] + member inline _.Zero() = task.Zero() + member inline _.Return (value) = task.Return(value) + member inline _.Combine(task1, task2) = task.Combine(task1, task2) + member inline _.While ([] condition, body) = task.While(condition, body) + member inline _.TryWith (body, catch) = task.TryWith(body, catch) + member inline _.TryFinally (body, compensation ) = task.TryFinally(body, compensation) +#if NETCOREAPP + member inline _.Using<'Resource, 'TOverall, 'T when 'Resource :> IAsyncDisposable> (resource: 'Resource, body: 'Resource -> TaskCode<'TOverall, 'T>) = + task.Using(resource, body) +#endif + member inline _.For (sequence, body) = task.For(sequence, body) + member inline _.ReturnFrom (t: Task<'T>) = task.ReturnFrom(t) + +// Delegates to task, except 'Run' which is deliberately not inlined, hence no chance +// of static compilation of state machines. +type BackgroundTaskBuilderDynamic() = + + [] + member _.Run(code) = backgroundTask.Run(code) // warning 3511 is generated here: state machine not compilable + + member inline _.Delay f = backgroundTask.Delay(f) + [] + member inline _.Zero() = backgroundTask.Zero() + member inline _.Return (value) = backgroundTask.Return(value) + member inline _.Combine(task1, task2) = backgroundTask.Combine(task1, task2) + member inline _.While ([] condition, body) = backgroundTask.While(condition, body) + member inline _.TryWith (body, catch) = backgroundTask.TryWith(body, catch) + member inline _.TryFinally (body, compensation ) = backgroundTask.TryFinally(body, compensation) +#if NETCOREAPP + member inline _.Using<'Resource, 'TOverall, 'T when 'Resource :> IAsyncDisposable> (resource: 'Resource, body: 'Resource -> TaskCode<'TOverall, 'T>) = + backgroundTask.Using(resource, body) +#endif + member inline _.For (sequence, body) = backgroundTask.For(sequence, body) + member inline _.ReturnFrom (t: Task<'T>) = backgroundTask.ReturnFrom(t) + +[] +module TaskBuilderDynamicLowPriority = + + // Low priority extension method + type TaskBuilderDynamic with + member inline _.Using<'Resource, 'TOverall, 'T when 'Resource :> IDisposable> (resource: 'Resource, body: 'Resource -> TaskCode<'TOverall, 'T>) = + task.Using(resource, body) + + // Low priority extension method + type BackgroundTaskBuilderDynamic with + member inline _.Using<'Resource, 'TOverall, 'T when 'Resource :> IDisposable> (resource: 'Resource, body: 'Resource -> TaskCode<'TOverall, 'T>) = + backgroundTask.Using(resource, body) + +[] +module Value = + + [] + module TaskLowProrityExtensions = + + type TaskBuilderDynamic with + member inline _.ReturnFrom< ^TaskLike, ^Awaiter, ^T + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> ^T)> + (t: ^TaskLike) : TaskCode< ^T, ^T> = + task.ReturnFrom(t) + member inline _.Bind< ^TaskLike, ^TResult1, 'TResult2, ^Awaiter , 'TOverall + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> ^TResult1)> + (t: ^TaskLike, continuation: (^TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> = + task.Bind(t, continuation) + + type BackgroundTaskBuilderDynamic with + member inline _.ReturnFrom< ^TaskLike, ^Awaiter, ^T + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> ^T)> + (t: ^TaskLike) : TaskCode< ^T, ^T> = + backgroundTask.ReturnFrom(t) + member inline _.Bind< ^TaskLike, ^TResult1, 'TResult2, ^Awaiter , 'TOverall + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> ^TResult1)> + (t: ^TaskLike, continuation: (^TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> = + backgroundTask.Bind(t, continuation) + + + [] + module HighLowProrityExtensions = + + type TaskBuilderDynamic with + member inline _.Bind (t: Task<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> = + task.Bind(t, continuation) + + member inline _.Bind (computation: Async<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> = + task.Bind(computation, continuation) + + member inline _.ReturnFrom (t: Task<'T>) : TaskCode<'T, 'T> = + task.ReturnFrom(t) + + member inline _.ReturnFrom (computation: Async<'T>) : TaskCode<'T, 'T> = + task.ReturnFrom(computation) + + + type BackgroundTaskBuilderDynamic with + member inline _.Bind (t: Task<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> = + backgroundTask.Bind(t, continuation) + + member inline _.Bind (computation: Async<'TResult1>, continuation: ('TResult1 -> TaskCode<'TOverall, 'TResult2>)) : TaskCode<'TOverall, 'TResult2> = + backgroundTask.Bind(computation, continuation) + + member inline _.ReturnFrom (task: Task<'T>) : TaskCode<'T, 'T> = + backgroundTask.ReturnFrom(task) + + member inline _.ReturnFrom (computation: Async<'T>) : TaskCode<'T, 'T> = + backgroundTask.ReturnFrom(computation) + + let taskDynamic = TaskBuilderDynamic() + let backgroundTaskDynamic = BackgroundTaskBuilderDynamic() + type Do_no_use_task_in_this_file_use_taskDynamic_instead = | Nope + let task = Do_no_use_task_in_this_file_use_taskDynamic_instead.Nope + +type ITaskThing = + abstract member Taskify : 'a option -> 'a Task + +type SmokeTestsForCompilation() = + + [] + member __.tinyTask() = + taskDynamic { + return 1 + } + |> fun t -> + t.Wait() + if t.Result <> 1 then failwith "failed" + + [] + member __.tbind() = + taskDynamic { + let! x = Task.FromResult(1) + return 1 + x + } + |> fun t -> + t.Wait() + if t.Result <> 2 then failwith "failed" + + [] + member __.tnested() = + taskDynamic { + let! x = taskDynamic { return 1 } + return x + } + |> fun t -> + t.Wait() + if t.Result <> 1 then failwith "failed" + + [] + member __.tcatch0() = + taskDynamic { + try + return 1 + with e -> + return 2 + } + |> fun t -> + t.Wait() + if t.Result <> 1 then failwith "failed" + + [] + member __.tcatch1() = + taskDynamic { + try + let! x = Task.FromResult 1 + return x + with e -> + return 2 + } + |> fun t -> + t.Wait() + if t.Result <> 1 then failwith "failed" + + + [] + member __.t3() = + let t2() = + taskDynamic { + System.Console.WriteLine("hello") + return 1 + } + taskDynamic { + System.Console.WriteLine("hello") + let! x = t2() + System.Console.WriteLine("world") + return 1 + x + } + |> fun t -> + t.Wait() + if t.Result <> 2 then failwith "failed" + + [] + member __.t3b() = + taskDynamic { + System.Console.WriteLine("hello") + let! x = Task.FromResult(1) + System.Console.WriteLine("world") + return 1 + x + } + |> fun t -> + t.Wait() + if t.Result <> 2 then failwith "failed" + + [] + member __.t3c() = + taskDynamic { + System.Console.WriteLine("hello") + do! Task.Delay(100) + System.Console.WriteLine("world") + return 1 + } + |> fun t -> + t.Wait() + if t.Result <> 1 then failwith "failed" + + [] + // This tests an exception match + member __.t67() = + taskDynamic { + try + do! Task.Delay(0) + with + | :? ArgumentException -> + () + | _ -> + () + } + |> fun t -> + t.Wait() + if t.Result <> () then failwith "failed" + + [] + // This tests compiling an incomplete exception match + member __.t68() = + taskDynamic { + try + do! Task.Delay(0) + with + | :? ArgumentException -> + () + } + |> fun t -> + t.Wait() + if t.Result <> () then failwith "failed" + + [] + member __.testCompileAsyncWhileLoop() = + taskDynamic { + let mutable i = 0 + while i < 5 do + i <- i + 1 + do! Task.Yield() + return i + } + |> fun t -> + t.Wait() + if t.Result <> 5 then failwith "failed" + + +exception TestException of string + +[] +module Helpers = + let BIG = 10 + // let BIG = 10000 + let require x msg = if not x then failwith msg + let failtest str = raise (TestException str) + +type Basics() = + [] + member __.testShortCircuitResult() = + printfn "Running testShortCircuitResult..." + let t = + taskDynamic { + let! x = Task.FromResult(1) + let! y = Task.FromResult(2) + return x + y + } + require t.IsCompleted "didn't short-circuit already completed tasks" + printfn "t.Result = %A" t.Result + require (t.Result = 3) "wrong result" + + [] + member __.testDelay() = + printfn "Running testDelay..." + let mutable x = 0 + let t = + taskDynamic { + do! Task.Delay(50) + x <- x + 1 + } + printfn "task created and first step run...." + require (x = 0) "task already ran" + printfn "waiting...." + t.Wait() + + [] + member __.testNoDelay() = + printfn "Running testNoDelay..." + let mutable x = 0 + let t = + taskDynamic { + x <- x + 1 + do! Task.Delay(5) + x <- x + 1 + } + require (x = 1) "first part didn't run yet" + t.Wait() + + [] + member __.testNonBlocking() = + printfn "Running testNonBlocking..." + let sw = Stopwatch() + sw.Start() + let t = + taskDynamic { + do! Task.Yield() + Thread.Sleep(100) + } + sw.Stop() + require (sw.ElapsedMilliseconds < 50L) "sleep blocked caller" + t.Wait() + + [] + member __.testCatching1() = + printfn "Running testCatching1..." + let mutable x = 0 + let mutable y = 0 + let t = + taskDynamic { + try + do! Task.Delay(0) + failtest "hello" + x <- 1 + do! Task.Delay(100) + with + | TestException msg -> + require (msg = "hello") "message tampered" + | _ -> + require false "other exn type" + require false "other exn type" + y <- 1 + } + t.Wait() + require (y = 1) "bailed after exn" + require (x = 0) "ran past failure" + + [] + member __.testCatching2() = + printfn "Running testCatching2..." + let mutable x = 0 + let mutable y = 0 + let t = + taskDynamic { + try + do! Task.Yield() // can't skip through this + failtest "hello" + x <- 1 + do! Task.Delay(100) + with + | TestException msg -> + require (msg = "hello") "message tampered" + | _ -> + require false "other exn type" + y <- 1 + } + t.Wait() + require (y = 1) "bailed after exn" + require (x = 0) "ran past failure" + + [] + member __.testNestedCatching() = + printfn "Running testNestedCatching..." + let mutable counter = 1 + let mutable caughtInner = 0 + let mutable caughtOuter = 0 + let t1() = + taskDynamic { + try + do! Task.Yield() + failtest "hello" + with + | TestException msg as exn -> + caughtInner <- counter + counter <- counter + 1 + raise exn + } + let t2 = + taskDynamic { + try + do! t1() + with + | TestException msg as exn -> + caughtOuter <- counter + raise exn + | e -> + require false (sprintf "invalid msg type %s" e.Message) + } + try + t2.Wait() + require false "ran past failed task wait" + with + | :? AggregateException as exn -> + require (exn.InnerExceptions.Count = 1) "more than 1 exn" + require (caughtInner = 1) "didn't catch inner" + require (caughtOuter = 2) "didn't catch outer" + + [] + member __.testWhileLoopSync() = + printfn "Running testWhileLoopSync..." + let t = + taskDynamic { + let mutable i = 0 + while i < 10 do + i <- i + 1 + return i + } + //t.Wait() no wait required for sync loop + require (t.IsCompleted) "didn't do sync while loop properly - not completed" + require (t.Result = 10) "didn't do sync while loop properly - wrong result" + + [] + member __.testWhileLoopAsyncZeroIteration() = + printfn "Running testWhileLoopAsyncZeroIteration..." + for i in 1 .. 5 do + let t = + taskDynamic { + let mutable i = 0 + while i < 0 do + i <- i + 1 + do! Task.Yield() + return i + } + t.Wait() + require (t.Result = 0) "didn't do while loop properly" + + [] + member __.testWhileLoopAsyncOneIteration() = + printfn "Running testWhileLoopAsyncOneIteration..." + for i in 1 .. 5 do + let t = + taskDynamic { + let mutable i = 0 + while i < 1 do + i <- i + 1 + do! Task.Yield() + return i + } + t.Wait() + require (t.Result = 1) "didn't do while loop properly" + + [] + member __.testWhileLoopAsync() = + printfn "Running testWhileLoopAsync..." + for i in 1 .. 5 do + let t = + taskDynamic { + let mutable i = 0 + while i < 10 do + i <- i + 1 + do! Task.Yield() + return i + } + t.Wait() + require (t.Result = 10) "didn't do while loop properly" + + [] + member __.testTryFinallyHappyPath() = + printfn "Running testTryFinallyHappyPath..." + for i in 1 .. 5 do + let mutable ran = false + let t = + taskDynamic { + try + require (not ran) "ran way early" + do! Task.Delay(100) + require (not ran) "ran kinda early" + finally + ran <- true + } + t.Wait() + require ran "never ran" + [] + member __.testTryFinallySadPath() = + printfn "Running testTryFinallySadPath..." + for i in 1 .. 5 do + let mutable ran = false + let t = + taskDynamic { + try + require (not ran) "ran way early" + do! Task.Delay(100) + require (not ran) "ran kinda early" + failtest "uhoh" + finally + ran <- true + } + try + t.Wait() + with + | _ -> () + require ran "never ran" + + [] + member __.testTryFinallyCaught() = + printfn "Running testTryFinallyCaught..." + for i in 1 .. 5 do + let mutable ran = false + let t = + taskDynamic { + try + try + require (not ran) "ran way early" + do! Task.Delay(100) + require (not ran) "ran kinda early" + failtest "uhoh" + finally + ran <- true + return 1 + with + | _ -> return 2 + } + require (t.Result = 2) "wrong return" + require ran "never ran" + + [] + member __.testUsing() = + printfn "Running testUsing..." + for i in 1 .. 5 do + let mutable disposed = false + let t = + taskDynamic { + use d = { new IDisposable with member __.Dispose() = disposed <- true } + require (not disposed) "disposed way early" + do! Task.Delay(100) + require (not disposed) "disposed kinda early" + } + t.Wait() + require disposed "never disposed B" + +#if NETCOREAPP + [] + member __.testUsingAsyncDisposableSync() = + printfn "Running testUsing..." + for i in 1 .. 5 do + let mutable disposed = 0 + let t = + taskDynamic { + use d = + { new IAsyncDisposable with + member __.DisposeAsync() = + taskDynamic { + System.Console.WriteLine "incrementing" + disposed <- disposed + 1 } + |> ValueTask + } + require (disposed = 0) "disposed way early" + System.Console.WriteLine "delaying" + do! Task.Delay(100) + System.Console.WriteLine "testing" + require (disposed = 0) "disposed kinda early" + } + t.Wait() + require (disposed >= 1) "never disposed B" + require (disposed <= 1) "too many dispose on B" + + [] + member __.testUsingAsyncDisposableAsync() = + printfn "Running testUsing..." + for i in 1 .. 5 do + let mutable disposed = 0 + let t = + taskDynamic { + use d = + { new IAsyncDisposable with + member __.DisposeAsync() = + taskDynamic { + do! Task.Delay(10) + disposed <- disposed + 1 + } + |> ValueTask + } + require (disposed = 0) "disposed way early" + do! Task.Delay(100) + require (disposed = 0) "disposed kinda early" + } + t.Wait() + require (disposed >= 1) "never disposed B" + require (disposed <= 1) "too many dispose on B" + + [] + member __.testUsingAsyncDisposableExnAsync() = + printfn "Running testUsing..." + for i in 1 .. 5 do + let mutable disposed = 0 + let t = + taskDynamic { + use d = + { new IAsyncDisposable with + member __.DisposeAsync() = + taskDynamic { + do! Task.Delay(10) + disposed <- disposed + 1 + } + |> ValueTask + } + require (disposed = 0) "disposed way early" + failtest "oops" + + } + try t.Wait() + with | :? AggregateException -> + require (disposed >= 1) "never disposed B" + require (disposed <= 1) "too many dispose on B" + + [] + member __.testUsingAsyncDisposableExnSync() = + printfn "Running testUsing..." + for i in 1 .. 5 do + let mutable disposed = 0 + let t = + taskDynamic { + use d = + { new IAsyncDisposable with + member __.DisposeAsync() = + taskDynamic { + disposed <- disposed + 1 + do! Task.Delay(10) + } + |> ValueTask + } + require (disposed = 0) "disposed way early" + failtest "oops" + + } + try t.Wait() + with | :? AggregateException -> + require (disposed >= 1) "never disposed B" + require (disposed <= 1) "too many dispose on B" + + [] + member __.testUsingAsyncDisposableDelayExnSync() = + printfn "Running testUsing..." + for i in 1 .. 5 do + let mutable disposed = 0 + let t = + taskDynamic { + use d = + { new IAsyncDisposable with + member __.DisposeAsync() = + taskDynamic { + disposed <- disposed + 1 + do! Task.Delay(10) + } + |> ValueTask + } + require (disposed = 0) "disposed way early" + do! Task.Delay(10) + require (disposed = 0) "disposed kind of early" + failtest "oops" + + } + try t.Wait() + with | :? AggregateException -> + require (disposed >= 1) "never disposed B" + require (disposed <= 1) "too many dispose on B" +#endif + + [] + member __.testUsingFromTask() = + printfn "Running testUsingFromTask..." + let mutable disposedInner = false + let mutable disposed = false + let t = + taskDynamic { + use! d = + taskDynamic { + do! Task.Delay(50) + use i = { new IDisposable with member __.Dispose() = disposedInner <- true } + require (not disposed && not disposedInner) "disposed inner early" + return { new IDisposable with member __.Dispose() = disposed <- true } + } + require disposedInner "did not dispose inner after task completion" + require (not disposed) "disposed way early" + do! Task.Delay(50) + require (not disposed) "disposed kinda early" + } + t.Wait() + require disposed "never disposed C" + + [] + member __.testUsingSadPath() = + printfn "Running testUsingSadPath..." + let mutable disposedInner = false + let mutable disposed = false + let t = + taskDynamic { + try + use! d = + taskDynamic { + do! Task.Delay(50) + use i = { new IDisposable with member __.Dispose() = disposedInner <- true } + failtest "uhoh" + require (not disposed && not disposedInner) "disposed inner early" + return { new IDisposable with member __.Dispose() = disposed <- true } + } + () + with + | TestException msg -> + printfn "caught TestException" + require disposedInner "did not dispose inner after task completion" + require (not disposed) "disposed way early" + do! Task.Delay(50) + printfn "resumed after delay" + require (not disposed) "disposed kinda early" + } + t.Wait() + require (not disposed) "disposed thing that never should've existed" + + [] + member __.testForLoopA() = + printfn "Running testForLoopA..." + let list = ["a"; "b"; "c"] |> Seq.ofList + let t = + taskDynamic { + printfn "entering loop..." + let mutable x = Unchecked.defaultof<_> + let e = list.GetEnumerator() + while e.MoveNext() do + x <- e.Current + printfn "x = %A" x + do! Task.Yield() + printfn "x = %A" x + } + t.Wait() + + [] + member __.testForLoopComplex() = + printfn "Running testForLoopComplex..." + let mutable disposed = false + let wrapList = + let raw = ["a"; "b"; "c"] |> Seq.ofList + let getEnumerator() = + let raw = raw.GetEnumerator() + { new IEnumerator with + member __.MoveNext() = + require (not disposed) "moved next after disposal" + raw.MoveNext() + member __.Current = + require (not disposed) "accessed current after disposal" + raw.Current + member __.Current = + require (not disposed) "accessed current (boxed) after disposal" + box raw.Current + member __.Dispose() = + require (not disposed) "disposed twice" + disposed <- true + raw.Dispose() + member __.Reset() = + require (not disposed) "reset after disposal" + raw.Reset() + } + { new IEnumerable with + member __.GetEnumerator() : IEnumerator = getEnumerator() + member __.GetEnumerator() : IEnumerator = upcast getEnumerator() + } + let t = + taskDynamic { + let mutable index = 0 + do! Task.Yield() + printfn "entering loop..." + for x in wrapList do + printfn "x = %A, index = %d" x index + do! Task.Yield() + printfn "back from yield" + do! Task.Yield() + printfn "back from yield" + match index with + | 0 -> require (x = "a") "wrong first value" + | 1 -> require (x = "b") "wrong second value" + | 2 -> require (x = "c") "wrong third value" + | _ -> require false "iterated too far!" + index <- index + 1 + printfn "yield again" + do! Task.Yield() + printfn "yield again again" + do! Task.Yield() + printfn "looping again..." + do! Task.Yield() + return 1 + } + t.Wait() + require disposed "never disposed D" + require (t.Result = 1) "wrong result" + + [] + member __.testForLoopSadPath() = + printfn "Running testForLoopSadPath..." + for i in 1 .. 5 do + let wrapList = ["a"; "b"; "c"] + let t = + taskDynamic { + let mutable index = 0 + do! Task.Yield() + for x in wrapList do + do! Task.Yield() + index <- index + 1 + return 1 + } + require (t.Result = 1) "wrong result" + + [] + member __.testForLoopSadPathComplex() = + printfn "Running testForLoopSadPathComplex..." + for i in 1 .. 5 do + let mutable disposed = false + let wrapList = + let raw = ["a"; "b"; "c"] |> Seq.ofList + let getEnumerator() = + let raw = raw.GetEnumerator() + { new IEnumerator with + member __.MoveNext() = + require (not disposed) "moved next after disposal" + raw.MoveNext() + member __.Current = + require (not disposed) "accessed current after disposal" + raw.Current + member __.Current = + require (not disposed) "accessed current (boxed) after disposal" + box raw.Current + member __.Dispose() = + require (not disposed) "disposed twice" + disposed <- true + raw.Dispose() + member __.Reset() = + require (not disposed) "reset after disposal" + raw.Reset() + } + { new IEnumerable with + member __.GetEnumerator() : IEnumerator = getEnumerator() + member __.GetEnumerator() : IEnumerator = upcast getEnumerator() + } + let mutable caught = false + let t = + taskDynamic { + try + let mutable index = 0 + do! Task.Yield() + for x in wrapList do + do! Task.Yield() + match index with + | 0 -> require (x = "a") "wrong first value" + | _ -> failtest "uhoh" + index <- index + 1 + do! Task.Yield() + do! Task.Yield() + return 1 + with + | TestException "uhoh" -> + caught <- true + return 2 + } + require (t.Result = 2) "wrong result" + require caught "didn't catch exception" + require disposed "never disposed A" + + [] + member __.testExceptionAttachedToTaskWithoutAwait() = + for i in 1 .. 5 do + let mutable ranA = false + let mutable ranB = false + let t = + taskDynamic { + ranA <- true + failtest "uhoh" + ranB <- true + } + require ranA "didn't run immediately" + require (not ranB) "ran past exception" + require (not (isNull t.Exception)) "didn't capture exception" + require (t.Exception.InnerExceptions.Count = 1) "captured more exceptions" + require (t.Exception.InnerException = TestException "uhoh") "wrong exception" + let mutable caught = false + let mutable ranCatcher = false + let catcher = + taskDynamic { + try + ranCatcher <- true + let! result = t + return false + with + | TestException "uhoh" -> + caught <- true + return true + } + require ranCatcher "didn't run" + require catcher.Result "didn't catch" + require caught "didn't catch" + + [] + member __.testExceptionAttachedToTaskWithAwait() = + printfn "running testExceptionAttachedToTaskWithAwait" + for i in 1 .. 5 do + let mutable ranA = false + let mutable ranB = false + let t = + taskDynamic { + ranA <- true + failtest "uhoh" + do! Task.Delay(100) + ranB <- true + } + require ranA "didn't run immediately" + require (not ranB) "ran past exception" + require (not (isNull t.Exception)) "didn't capture exception" + require (t.Exception.InnerExceptions.Count = 1) "captured more exceptions" + require (t.Exception.InnerException = TestException "uhoh") "wrong exception" + let mutable caught = false + let mutable ranCatcher = false + let catcher = + taskDynamic { + try + ranCatcher <- true + let! result = t + return false + with + | TestException "uhoh" -> + caught <- true + return true + } + require ranCatcher "didn't run" + require catcher.Result "didn't catch" + require caught "didn't catch" + + [] + member __.testExceptionThrownInFinally() = + printfn "running testExceptionThrownInFinally" + for i in 1 .. 5 do + let mutable ranInitial = false + let mutable ranNext = false + let mutable ranFinally = 0 + let t = + taskDynamic { + try + ranInitial <- true + do! Task.Yield() + Thread.Sleep(100) // shouldn't be blocking so we should get through to requires before this finishes + ranNext <- true + finally + ranFinally <- ranFinally + 1 + failtest "finally exn!" + } + require ranInitial "didn't run initial" + require (not ranNext) "ran next too early" + try + t.Wait() + require false "shouldn't get here" + with + | _ -> () + require ranNext "didn't run next" + require (ranFinally = 1) "didn't run finally exactly once" + + [] + member __.test2ndExceptionThrownInFinally() = + printfn "running test2ndExceptionThrownInFinally" + for i in 1 .. 5 do + let mutable ranInitial = false + let mutable ranNext = false + let mutable ranFinally = 0 + let t = + taskDynamic { + try + ranInitial <- true + do! Task.Yield() + Thread.Sleep(100) // shouldn't be blocking so we should get through to requires before this finishes + ranNext <- true + failtest "uhoh" + finally + ranFinally <- ranFinally + 1 + failtest "2nd exn!" + } + require ranInitial "didn't run initial" + require (not ranNext) "ran next too early" + try + t.Wait() + require false "shouldn't get here" + with + | _ -> () + require ranNext "didn't run next" + require (ranFinally = 1) "didn't run finally exactly once" + + [] + member __.testFixedStackWhileLoop() = + printfn "running testFixedStackWhileLoop" + for i in 1 .. 100 do + let t = + taskDynamic { + let mutable maxDepth = Nullable() + let mutable i = 0 + while i < BIG do + i <- i + 1 + do! Task.Yield() + if i % 100 = 0 then + let stackDepth = StackTrace().FrameCount + if maxDepth.HasValue && stackDepth > maxDepth.Value then + failwith "Stack depth increased!" + maxDepth <- Nullable(stackDepth) + return i + } + t.Wait() + require (t.Result = BIG) "didn't get to big number" + + [] + member __.testFixedStackForLoop() = + for i in 1 .. 100 do + printfn "running testFixedStackForLoop" + let mutable ran = false + let t = + taskDynamic { + let mutable maxDepth = Nullable() + for i in Seq.init BIG id do + do! Task.Yield() + if i % 100 = 0 then + let stackDepth = StackTrace().FrameCount + if maxDepth.HasValue && stackDepth > maxDepth.Value then + failwith "Stack depth increased!" + maxDepth <- Nullable(stackDepth) + ran <- true + return () + } + t.Wait() + require ran "didn't run all" + + [] + member __.testTypeInference() = + let t1 : string Task = + taskDynamic { + return "hello" + } + let t2 = + taskDynamic { + let! s = t1 + return s.Length + } + t2.Wait() + + [] + member __.testNoStackOverflowWithImmediateResult() = + printfn "running testNoStackOverflowWithImmediateResult" + let longLoop = + taskDynamic { + let mutable n = 0 + while n < BIG do + n <- n + 1 + return! Task.FromResult(()) + } + longLoop.Wait() + + [] + member __.testNoStackOverflowWithYieldResult() = + printfn "running testNoStackOverflowWithYieldResult" + let longLoop = + taskDynamic { + let mutable n = 0 + while n < BIG do + let! _ = + taskDynamic { + do! Task.Yield() + let! _ = Task.FromResult(0) + n <- n + 1 + } + n <- n + 1 + } + longLoop.Wait() + + [] + member __.testSmallTailRecursion() = + printfn "running testSmallTailRecursion" + let rec loop n = + taskDynamic { + if n < 100 then + do! Task.Yield() + let! _ = Task.FromResult(0) + return! loop (n + 1) + else + return () + } + let shortLoop = + taskDynamic { + return! loop 0 + } + shortLoop.Wait() + + [] + member __.testTryOverReturnFrom() = + printfn "running testTryOverReturnFrom" + let inner() = + taskDynamic { + do! Task.Yield() + failtest "inner" + return 1 + } + let t = + taskDynamic { + try + do! Task.Yield() + return! inner() + with + | TestException "inner" -> return 2 + } + require (t.Result = 2) "didn't catch" + + [] + member __.testTryFinallyOverReturnFromWithException() = + printfn "running testTryFinallyOverReturnFromWithException" + let inner() = + taskDynamic { + do! Task.Yield() + failtest "inner" + return 1 + } + let mutable m = 0 + let t = + taskDynamic { + try + do! Task.Yield() + return! inner() + finally + m <- 1 + } + try + t.Wait() + with + | :? AggregateException -> () + require (m = 1) "didn't run finally" + + [] + member __.testTryFinallyOverReturnFromWithoutException() = + printfn "running testTryFinallyOverReturnFromWithoutException" + let inner() = + taskDynamic { + do! Task.Yield() + return 1 + } + let mutable m = 0 + let t = + taskDynamic { + try + do! Task.Yield() + return! inner() + finally + m <- 1 + } + try + t.Wait() + with + | :? AggregateException -> () + require (m = 1) "didn't run finally" + + // no need to call this, we just want to check that it compiles w/o warnings + member __.testTrivialReturnCompiles (x : 'a) : 'a Task = + taskDynamic { + do! Task.Yield() + return x + } + + // no need to call this, we just want to check that it compiles w/o warnings + member __.testTrivialTransformedReturnCompiles (x : 'a) (f : 'a -> 'b) : 'b Task = + taskDynamic { + do! Task.Yield() + return f x + } + + [] + member __.testAsyncsMixedWithTasks() = + let t = + taskDynamic { + do! Task.Delay(1) + do! Async.Sleep(1) + let! x = + async { + do! Async.Sleep(1) + return 5 + } + return! async { return x + 3 } + } + let result = t.Result + require (result = 8) "something weird happened" + + [] + // no need to call this, we just want to check that it compiles w/o warnings + member __.testDefaultInferenceForReturnFrom() = + let t = taskDynamic { return Some "x" } + taskDynamic { + let! r = t + if r = None then + return! failwithf "Could not find x" + else + return r + } + |> ignore + + [] + // no need to call this, just check that it compiles + member __.testCompilerInfersArgumentOfReturnFrom() = + taskDynamic { + if true then return 1 + else return! failwith "" + } + |> ignore + + +[] +type BasicsNotInParallel() = + + [] + member __.testTaskUsesSyncContext() = + printfn "Running testBackgroundTask..." + for i in 1 .. 5 do + let mutable ran = false + let mutable posted = false + let oldSyncContext = SynchronizationContext.Current + let syncContext = { new SynchronizationContext() with member _.Post(d,state) = posted <- true; d.Invoke(state) } + try + SynchronizationContext.SetSynchronizationContext syncContext + let tid = System.Threading.Thread.CurrentThread.ManagedThreadId + require (not (isNull SynchronizationContext.Current)) "need sync context non null on foreground thread A" + require (SynchronizationContext.Current = syncContext) "need sync context known on foreground thread A" + let t = + taskDynamic { + let tid2 = System.Threading.Thread.CurrentThread.ManagedThreadId + require (not (isNull SynchronizationContext.Current)) "need sync context non null on foreground thread B" + require (SynchronizationContext.Current = syncContext) "need sync context known on foreground thread B" + require (tid = tid2) "expected synchronous start for task B2" + do! Task.Yield() + require (not (isNull SynchronizationContext.Current)) "need sync context non null on foreground thread C" + require (SynchronizationContext.Current = syncContext) "need sync context known on foreground thread C" + ran <- true + } + t.Wait() + require ran "never ran" + require posted "never posted" + finally + SynchronizationContext.SetSynchronizationContext oldSyncContext + + [] + member __.testBackgroundTaskEscapesSyncContext() = + printfn "Running testBackgroundTask..." + for i in 1 .. 5 do + let mutable ran = false + let mutable posted = false + let oldSyncContext = SynchronizationContext.Current + let syncContext = { new SynchronizationContext() with member _.Post(d,state) = posted <- true; d.Invoke(state) } + try + SynchronizationContext.SetSynchronizationContext syncContext + let t = + backgroundTaskDynamic { + require (System.Threading.Thread.CurrentThread.IsThreadPoolThread) "expect to be on background thread" + ran <- true + } + t.Wait() + require ran "never ran" + require (not posted) "did not expect post to sync context" + finally + SynchronizationContext.SetSynchronizationContext oldSyncContext + + [] + member __.testBackgroundTaskStaysOnSameThreadIfAlreadyOnBackground() = + printfn "Running testBackgroundTask..." + for i in 1 .. 5 do + let mutable ran = false + let taskOuter = + Task.Run(fun () -> + let tid = System.Threading.Thread.CurrentThread.ManagedThreadId + // In case other thread pool activities have polluted this one, sigh + SynchronizationContext.SetSynchronizationContext null + require (System.Threading.Thread.CurrentThread.IsThreadPoolThread) "expected thread pool thread (1)" + let t = + backgroundTaskDynamic { + require (System.Threading.Thread.CurrentThread.IsThreadPoolThread) "expected thread pool thread (2)" + let tid2 = System.Threading.Thread.CurrentThread.ManagedThreadId + require (tid = tid2) "expected synchronous starts when already on thread pool thread with null sync context" + do! Task.Delay(200) + ran <- true + } + t.Wait() + require ran "never ran") + taskOuter.Wait() + +#if STANDALONE +module M = + [] + let main argv = + printfn "Running tests..." + try + Basics().testShortCircuitResult() + Basics().testDelay() + Basics().testNoDelay() + Basics().testNonBlocking() + + Basics().testCatching1() + Basics().testCatching2() + Basics().testNestedCatching() + Basics().testWhileLoopSync() + Basics().testWhileLoopAsyncZeroIteration() + Basics().testWhileLoopAsyncOneIteration() + Basics().testWhileLoopAsync() + Basics().testTryFinallyHappyPath() + Basics().testTryFinallySadPath() + Basics().testTryFinallyCaught() + Basics().testUsing() + Basics().testUsingFromTask() + Basics().testUsingSadPath() + Basics().testForLoopA() + Basics().testForLoopSadPath() + Basics().testForLoopSadPathComplex() + Basics().testExceptionAttachedToTaskWithoutAwait() + Basics().testExceptionAttachedToTaskWithAwait() + Basics().testExceptionThrownInFinally() + Basics().test2ndExceptionThrownInFinally() + Basics().testFixedStackWhileLoop() + Basics().testFixedStackForLoop() + Basics().testTypeInference() + Basics().testNoStackOverflowWithImmediateResult() + Basics().testNoStackOverflowWithYieldResult() + ////// we don't support TCO, so large tail recursions will stack overflow + ////// or at least use O(n) heap. but small ones should at least function OK. + //testSmallTailRecursion() + Basics().testTryOverReturnFrom() + Basics().testTryFinallyOverReturnFromWithException() + Basics().testTryFinallyOverReturnFromWithoutException() + Basics().testAsyncsMixedWithTasks() + printfn "Passed all tests!" + with exn -> + eprintfn "************************************" + eprintfn "Exception: %O" exn + printfn "Test failed... exiting..." + eprintfn "************************************" + exit 1 + + printfn "Tests passed ok..., sleeping a bit in case there are background delayed exceptions" + Thread.Sleep(500) + printfn "Exiting..." + //System.Console.ReadLine() + 0 +#endif diff --git a/tests/FSharp.Core.UnitTests/LibraryTestFx.fs b/tests/FSharp.Core.UnitTests/LibraryTestFx.fs index 038b6d7014b..70697fb43e3 100644 --- a/tests/FSharp.Core.UnitTests/LibraryTestFx.fs +++ b/tests/FSharp.Core.UnitTests/LibraryTestFx.fs @@ -83,10 +83,10 @@ module SurfaceArea = let cast (info: #MemberInfo) = (t, info :> MemberInfo) let isDeclaredInFSharpCore (m:MemberInfo) = m.DeclaringType.Assembly.FullName = fsCoreFullName seq { - yield! t.GetRuntimeEvents() |> Seq.filter (fun m -> m.AddMethod.IsPublic && m |> isDeclaredInFSharpCore) |> Seq.map cast - yield! t.GetRuntimeProperties() |> Seq.filter (fun m -> m.GetMethod.IsPublic && m |> isDeclaredInFSharpCore) |> Seq.map cast - yield! t.GetRuntimeMethods() |> Seq.filter (fun m -> m.IsPublic && m |> isDeclaredInFSharpCore) |> Seq.map cast - yield! t.GetRuntimeFields() |> Seq.filter (fun m -> m.IsPublic && m |> isDeclaredInFSharpCore) |> Seq.map cast + yield! ti.DeclaredEvents |> Seq.filter (fun m -> m.AddMethod.IsPublic && m |> isDeclaredInFSharpCore) |> Seq.map cast + yield! ti.DeclaredProperties |> Seq.filter (fun m -> m.GetMethod.IsPublic && m |> isDeclaredInFSharpCore) |> Seq.map cast + yield! ti.DeclaredMethods |> Seq.filter (fun m -> m.IsPublic && m |> isDeclaredInFSharpCore) |> Seq.map cast + yield! ti.DeclaredFields |> Seq.filter (fun m -> m.IsPublic && m |> isDeclaredInFSharpCore) |> Seq.map cast yield! ti.DeclaredConstructors |> Seq.filter (fun m -> m.IsPublic) |> Seq.map cast yield! ti.DeclaredNestedTypes |> Seq.filter (fun ty -> ty.IsNestedPublic) |> Seq.map cast } |> Array.ofSeq diff --git a/tests/FSharp.Core.UnitTests/SurfaceArea.fs b/tests/FSharp.Core.UnitTests/SurfaceArea.fs index d9b71fec864..6ef1b853317 100644 --- a/tests/FSharp.Core.UnitTests/SurfaceArea.fs +++ b/tests/FSharp.Core.UnitTests/SurfaceArea.fs @@ -92,6 +92,7 @@ Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T[],T[]] Partition[T](M Microsoft.FSharp.Collections.ArrayModule: System.Tuple`2[T[],T[]] SplitAt[T](Int32, T[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`3[T1,T2,T3][] Zip3[T1,T2,T3](T1[], T2[], T3[]) Microsoft.FSharp.Collections.ArrayModule: System.Tuple`3[T1[],T2[],T3[]] Unzip3[T1,T2,T3](System.Tuple`3[T1,T2,T3][]) +Microsoft.FSharp.Collections.ArrayModule: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) Microsoft.FSharp.Collections.ArrayModule: T Average[T](T[]) Microsoft.FSharp.Collections.ArrayModule: T ExactlyOne[T](T[]) Microsoft.FSharp.Collections.ArrayModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], T[]) @@ -106,9 +107,12 @@ Microsoft.FSharp.Collections.ArrayModule: T MinBy[T,TResult](Microsoft.FSharp.Co Microsoft.FSharp.Collections.ArrayModule: T Min[T](T[]) Microsoft.FSharp.Collections.ArrayModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) Microsoft.FSharp.Collections.ArrayModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) +Microsoft.FSharp.Collections.ArrayModule: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) Microsoft.FSharp.Collections.ArrayModule: T Sum[T](T[]) +Microsoft.FSharp.Collections.ArrayModule: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], T[]) +Microsoft.FSharp.Collections.ArrayModule: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) Microsoft.FSharp.Collections.ArrayModule: TResult[] Choose[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], T[]) Microsoft.FSharp.Collections.ArrayModule: TResult[] Collect[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult[]], T[]) @@ -169,6 +173,7 @@ Microsoft.FSharp.Collections.ArrayModule: Void SortInPlaceBy[T,TKey](Microsoft.F Microsoft.FSharp.Collections.ArrayModule: Void SortInPlaceWith[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]], T[]) Microsoft.FSharp.Collections.ArrayModule: Void SortInPlace[T](T[]) Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] FromFunction[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32]]) +Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] NonStructural$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]]) Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] NonStructural[T]() Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] Structural[T]() Microsoft.FSharp.Collections.FSharpList`1+Tags[T]: Int32 Cons @@ -216,9 +221,9 @@ Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue]: Int32 Count Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue]: Int32 GetHashCode() Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue]: Int32 get_Count() Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue]: Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue] Add(TKey, TValue) +Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue]: Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue] Change(TKey, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpOption`1[TValue],Microsoft.FSharp.Core.FSharpOption`1[TValue]]) Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue]: Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue] Remove(TKey) Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue]: Microsoft.FSharp.Core.FSharpOption`1[TValue] TryFind(TKey) -Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue]: Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue] Change(TKey, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpOption`1[TValue],Microsoft.FSharp.Core.FSharpOption`1[TValue]]) Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue]: System.String ToString() Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue]: TValue Item [TKey] Microsoft.FSharp.Collections.FSharpMap`2[TKey,TValue]: TValue get_Item(TKey) @@ -246,6 +251,7 @@ Microsoft.FSharp.Collections.FSharpSet`1[T]: T get_MinimumElement() Microsoft.FSharp.Collections.FSharpSet`1[T]: Void .ctor(System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] FromFunctions[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]]) Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] LimitedStructural[T](Int32) +Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] NonStructural$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]]) Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] NonStructural[T]() Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] Reference[T]() Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] Structural[T]() @@ -322,6 +328,7 @@ Microsoft.FSharp.Collections.ListModule: System.Tuple`2[Microsoft.FSharp.Collect Microsoft.FSharp.Collections.ListModule: System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[T],Microsoft.FSharp.Collections.FSharpList`1[T]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: System.Tuple`2[Microsoft.FSharp.Collections.FSharpList`1[T],Microsoft.FSharp.Collections.FSharpList`1[T]] SplitAt[T](Int32, Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: System.Tuple`3[Microsoft.FSharp.Collections.FSharpList`1[T1],Microsoft.FSharp.Collections.FSharpList`1[T2],Microsoft.FSharp.Collections.FSharpList`1[T3]] Unzip3[T1,T2,T3](Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`3[T1,T2,T3]]) +Microsoft.FSharp.Collections.ListModule: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: T Average[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: T ExactlyOne[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Collections.FSharpList`1[T]) @@ -336,9 +343,12 @@ Microsoft.FSharp.Collections.ListModule: T MinBy[T,TResult](Microsoft.FSharp.Cor Microsoft.FSharp.Collections.ListModule: T Min[T](Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: T Sum[T](Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], Microsoft.FSharp.Collections.FSharpList`1[T]) +Microsoft.FSharp.Collections.ListModule: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Collections.ListModule: TState Fold2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TState]]], TState, Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2]) Microsoft.FSharp.Collections.ListModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], Microsoft.FSharp.Collections.FSharpList`1[T1], Microsoft.FSharp.Collections.FSharpList`1[T2], TState) @@ -357,6 +367,7 @@ Microsoft.FSharp.Collections.MapModule: Int32 Count[TKey,T](Microsoft.FSharp.Col Microsoft.FSharp.Collections.MapModule: Microsoft.FSharp.Collections.FSharpList`1[System.Tuple`2[TKey,T]] ToList[TKey,T](Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) Microsoft.FSharp.Collections.MapModule: Microsoft.FSharp.Collections.FSharpMap`2[TKey,TResult] Map[TKey,T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) Microsoft.FSharp.Collections.MapModule: Microsoft.FSharp.Collections.FSharpMap`2[TKey,T] Add[TKey,T](TKey, T, Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) +Microsoft.FSharp.Collections.MapModule: Microsoft.FSharp.Collections.FSharpMap`2[TKey,T] Change[TKey,T](TKey, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpOption`1[T],Microsoft.FSharp.Core.FSharpOption`1[T]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) Microsoft.FSharp.Collections.MapModule: Microsoft.FSharp.Collections.FSharpMap`2[TKey,T] Empty[TKey,T]() Microsoft.FSharp.Collections.MapModule: Microsoft.FSharp.Collections.FSharpMap`2[TKey,T] Filter[TKey,T](Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) Microsoft.FSharp.Collections.MapModule: Microsoft.FSharp.Collections.FSharpMap`2[TKey,T] OfArray[TKey,T](System.Tuple`2[TKey,T][]) @@ -375,7 +386,6 @@ Microsoft.FSharp.Collections.MapModule: TResult Pick[TKey,T,TResult](Microsoft.F Microsoft.FSharp.Collections.MapModule: TState FoldBack[TKey,T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T], TState) Microsoft.FSharp.Collections.MapModule: TState Fold[TKey,T,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,TState]]], TState, Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) Microsoft.FSharp.Collections.MapModule: Void Iterate[TKey,T](Microsoft.FSharp.Core.FSharpFunc`2[TKey,Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) -Microsoft.FSharp.Collections.MapModule: Microsoft.FSharp.Collections.FSharpMap`2[TKey,T] Change[TKey,T](TKey, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpOption`1[T],Microsoft.FSharp.Core.FSharpOption`1[T]], Microsoft.FSharp.Collections.FSharpMap`2[TKey,T]) Microsoft.FSharp.Collections.SeqModule: Boolean Contains[T](T, System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: Boolean Exists2[T1,T2](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,System.Boolean]], System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: Boolean Exists[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) @@ -450,6 +460,7 @@ Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1 Microsoft.FSharp.Collections.SeqModule: System.Collections.Generic.IEnumerable`1[T] Where[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: System.Tuple`2[System.Collections.Generic.IEnumerable`1[TResult],TState] MapFoldBack[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TState,System.Tuple`2[TResult,TState]]], System.Collections.Generic.IEnumerable`1[T], TState) Microsoft.FSharp.Collections.SeqModule: System.Tuple`2[System.Collections.Generic.IEnumerable`1[TResult],TState] MapFold[T,TState,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Tuple`2[TResult,TState]]], TState, System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: T Average[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: T ExactlyOne[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: T FindBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) @@ -464,9 +475,12 @@ Microsoft.FSharp.Collections.SeqModule: T MinBy[T,TResult](Microsoft.FSharp.Core Microsoft.FSharp.Collections.SeqModule: T Min[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: T ReduceBack[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: T Reduce[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: T Sum[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: TResult AverageBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: TResult Pick[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpOption`1[TResult]], System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Collections.SeqModule: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: TResult SumBy[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Collections.SeqModule: TState Fold2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[TState,Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TState]]], TState, System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2]) Microsoft.FSharp.Collections.SeqModule: TState FoldBack2[T1,T2,TState](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[TState,TState]]], System.Collections.Generic.IEnumerable`1[T1], System.Collections.Generic.IEnumerable`1[T2], TState) @@ -521,6 +535,8 @@ Microsoft.FSharp.Control.AsyncPrimitives: Microsoft.FSharp.Control.AsyncReturn I Microsoft.FSharp.Control.AsyncPrimitives: Microsoft.FSharp.Control.AsyncReturn TryFinally[T](Microsoft.FSharp.Control.AsyncActivation`1[T], Microsoft.FSharp.Control.FSharpAsync`1[T], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit]) Microsoft.FSharp.Control.AsyncPrimitives: Microsoft.FSharp.Control.AsyncReturn TryWith[T](Microsoft.FSharp.Control.AsyncActivation`1[T], Microsoft.FSharp.Control.FSharpAsync`1[T], Microsoft.FSharp.Core.FSharpFunc`2[System.Exception,Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Control.FSharpAsync`1[T]]]) Microsoft.FSharp.Control.AsyncPrimitives: Microsoft.FSharp.Control.FSharpAsync`1[T] MakeAsync[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Control.AsyncActivation`1[T],Microsoft.FSharp.Control.AsyncReturn]) +Microsoft.FSharp.Control.BackgroundTaskBuilder: System.Threading.Tasks.Task`1[T] RunDynamic[T](Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[T],T]) +Microsoft.FSharp.Control.BackgroundTaskBuilder: System.Threading.Tasks.Task`1[T] Run[T](Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[T],T]) Microsoft.FSharp.Control.CommonExtensions: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] AsyncWrite(System.IO.Stream, Byte[], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Control.CommonExtensions: Microsoft.FSharp.Control.FSharpAsync`1[System.Byte[]] AsyncReadBytes(System.IO.Stream, Int32) Microsoft.FSharp.Control.CommonExtensions: Microsoft.FSharp.Control.FSharpAsync`1[System.Int32] AsyncRead(System.IO.Stream, Byte[], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) @@ -635,6 +651,34 @@ Microsoft.FSharp.Control.ObservableModule: System.IObservable`1[T] Merge[T](Syst Microsoft.FSharp.Control.ObservableModule: System.Tuple`2[System.IObservable`1[TResult1],System.IObservable`1[TResult2]] Split[T,TResult1,TResult2](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpChoice`2[TResult1,TResult2]], System.IObservable`1[T]) Microsoft.FSharp.Control.ObservableModule: System.Tuple`2[System.IObservable`1[T],System.IObservable`1[T]] Partition[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], System.IObservable`1[T]) Microsoft.FSharp.Control.ObservableModule: Void Add[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], System.IObservable`1[T]) +Microsoft.FSharp.Control.TaskBuilder: System.Threading.Tasks.Task`1[T] RunDynamic[T](Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[T],T]) +Microsoft.FSharp.Control.TaskBuilder: System.Threading.Tasks.Task`1[T] Run[T](Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[T],T]) +Microsoft.FSharp.Control.TaskBuilderBase: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],Microsoft.FSharp.Core.Unit] For[T,TOverall](System.Collections.Generic.IEnumerable`1[T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],Microsoft.FSharp.Core.Unit]]) +Microsoft.FSharp.Control.TaskBuilderBase: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],Microsoft.FSharp.Core.Unit] While[TOverall](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Boolean], Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],Microsoft.FSharp.Core.Unit]) +Microsoft.FSharp.Control.TaskBuilderBase: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],Microsoft.FSharp.Core.Unit] Zero[TOverall]() +Microsoft.FSharp.Control.TaskBuilderBase: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T] Combine[TOverall,T](Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T]) +Microsoft.FSharp.Control.TaskBuilderBase: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T] Delay[TOverall,T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T]]) +Microsoft.FSharp.Control.TaskBuilderBase: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T] TryFinally[TOverall,T](Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit]) +Microsoft.FSharp.Control.TaskBuilderBase: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T] TryWith[TOverall,T](Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T], Microsoft.FSharp.Core.FSharpFunc`2[System.Exception,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T]]) +Microsoft.FSharp.Control.TaskBuilderBase: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[T],T] Return[T](T) +Microsoft.FSharp.Control.TaskBuilderExtensions.HighPriority: Boolean TaskBuilderBase.BindDynamic.Static[TOverall,TResult1,TResult2](Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall]] ByRef, System.Threading.Tasks.Task`1[TResult1], Microsoft.FSharp.Core.FSharpFunc`2[TResult1,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],TResult2]]) +Microsoft.FSharp.Control.TaskBuilderExtensions.HighPriority: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],TResult2] TaskBuilderBase.Bind[TResult1,TOverall,TResult2](Microsoft.FSharp.Control.TaskBuilderBase, System.Threading.Tasks.Task`1[TResult1], Microsoft.FSharp.Core.FSharpFunc`2[TResult1,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],TResult2]]) +Microsoft.FSharp.Control.TaskBuilderExtensions.HighPriority: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[T],T] TaskBuilderBase.ReturnFrom[T](Microsoft.FSharp.Control.TaskBuilderBase, System.Threading.Tasks.Task`1[T]) +Microsoft.FSharp.Control.TaskBuilderExtensions.LowPriority: Boolean TaskBuilderBase.BindDynamic.Static$W[TTaskLike,TResult1,TResult2,TAwaiter,TOverall](Microsoft.FSharp.Core.FSharpFunc`2[TTaskLike,TAwaiter], Microsoft.FSharp.Core.FSharpFunc`2[TAwaiter,TResult1], Microsoft.FSharp.Core.FSharpFunc`2[TAwaiter,System.Boolean], Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall]] ByRef, TTaskLike, Microsoft.FSharp.Core.FSharpFunc`2[TResult1,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],TResult2]]) +Microsoft.FSharp.Control.TaskBuilderExtensions.LowPriority: Boolean TaskBuilderBase.BindDynamic.Static[TTaskLike,TResult1,TResult2,TAwaiter,TOverall](Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall]] ByRef, TTaskLike, Microsoft.FSharp.Core.FSharpFunc`2[TResult1,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],TResult2]]) +Microsoft.FSharp.Control.TaskBuilderExtensions.LowPriority: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],TResult2] TaskBuilderBase.Bind$W[TTaskLike,TResult1,TResult2,TAwaiter,TOverall](Microsoft.FSharp.Core.FSharpFunc`2[TTaskLike,TAwaiter], Microsoft.FSharp.Core.FSharpFunc`2[TAwaiter,TResult1], Microsoft.FSharp.Core.FSharpFunc`2[TAwaiter,System.Boolean], Microsoft.FSharp.Control.TaskBuilderBase, TTaskLike, Microsoft.FSharp.Core.FSharpFunc`2[TResult1,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],TResult2]]) +Microsoft.FSharp.Control.TaskBuilderExtensions.LowPriority: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],TResult2] TaskBuilderBase.Bind[TTaskLike,TResult1,TResult2,TAwaiter,TOverall](Microsoft.FSharp.Control.TaskBuilderBase, TTaskLike, Microsoft.FSharp.Core.FSharpFunc`2[TResult1,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],TResult2]]) +Microsoft.FSharp.Control.TaskBuilderExtensions.LowPriority: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T] TaskBuilderBase.Using[TResource,TOverall,T](Microsoft.FSharp.Control.TaskBuilderBase, TResource, Microsoft.FSharp.Core.FSharpFunc`2[TResource,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T]]) +Microsoft.FSharp.Control.TaskBuilderExtensions.LowPriority: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[T],T] TaskBuilderBase.ReturnFrom$W[TTaskLike,TAwaiter,T](Microsoft.FSharp.Core.FSharpFunc`2[TTaskLike,TAwaiter], Microsoft.FSharp.Core.FSharpFunc`2[TAwaiter,T], Microsoft.FSharp.Core.FSharpFunc`2[TAwaiter,System.Boolean], Microsoft.FSharp.Control.TaskBuilderBase, TTaskLike) +Microsoft.FSharp.Control.TaskBuilderExtensions.LowPriority: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[T],T] TaskBuilderBase.ReturnFrom[TTaskLike,TAwaiter,T](Microsoft.FSharp.Control.TaskBuilderBase, TTaskLike) +Microsoft.FSharp.Control.TaskBuilderExtensions.MediumPriority: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],TResult2] TaskBuilderBase.Bind[TResult1,TOverall,TResult2](Microsoft.FSharp.Control.TaskBuilderBase, Microsoft.FSharp.Control.FSharpAsync`1[TResult1], Microsoft.FSharp.Core.FSharpFunc`2[TResult1,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],TResult2]]) +Microsoft.FSharp.Control.TaskBuilderExtensions.MediumPriority: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[T],T] TaskBuilderBase.ReturnFrom[T](Microsoft.FSharp.Control.TaskBuilderBase, Microsoft.FSharp.Control.FSharpAsync`1[T]) +Microsoft.FSharp.Control.TaskBuilderModule: Microsoft.FSharp.Control.BackgroundTaskBuilder backgroundTask +Microsoft.FSharp.Control.TaskBuilderModule: Microsoft.FSharp.Control.BackgroundTaskBuilder get_backgroundTask() +Microsoft.FSharp.Control.TaskBuilderModule: Microsoft.FSharp.Control.TaskBuilder get_task() +Microsoft.FSharp.Control.TaskBuilderModule: Microsoft.FSharp.Control.TaskBuilder task +Microsoft.FSharp.Control.TaskStateMachineData`1[T]: System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[T] MethodBuilder +Microsoft.FSharp.Control.TaskStateMachineData`1[T]: T Result Microsoft.FSharp.Control.WebExtensions: Microsoft.FSharp.Control.FSharpAsync`1[Microsoft.FSharp.Core.Unit] AsyncDownloadFile(System.Net.WebClient, System.Uri, System.String) Microsoft.FSharp.Control.WebExtensions: Microsoft.FSharp.Control.FSharpAsync`1[System.Byte[]] AsyncDownloadData(System.Net.WebClient, System.Uri) Microsoft.FSharp.Control.WebExtensions: Microsoft.FSharp.Control.FSharpAsync`1[System.Net.WebResponse] AsyncGetResponse(System.Net.WebRequest) @@ -702,6 +746,10 @@ Microsoft.FSharp.Core.CompilerMessageAttribute: System.String get_Message() Microsoft.FSharp.Core.CompilerMessageAttribute: Void .ctor(System.String, Int32) Microsoft.FSharp.Core.CompilerMessageAttribute: Void set_IsError(Boolean) Microsoft.FSharp.Core.CompilerMessageAttribute: Void set_IsHidden(Boolean) +Microsoft.FSharp.Core.CompilerServices.AfterCode`2[TData,TResult]: System.IAsyncResult BeginInvoke(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef, System.AsyncCallback, System.Object) +Microsoft.FSharp.Core.CompilerServices.AfterCode`2[TData,TResult]: TResult EndInvoke(System.IAsyncResult) +Microsoft.FSharp.Core.CompilerServices.AfterCode`2[TData,TResult]: TResult Invoke(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef) +Microsoft.FSharp.Core.CompilerServices.AfterCode`2[TData,TResult]: Void .ctor(System.Object, IntPtr) Microsoft.FSharp.Core.CompilerServices.ArrayCollector`1[T]: T[] Close() Microsoft.FSharp.Core.CompilerServices.ArrayCollector`1[T]: Void Add(T) Microsoft.FSharp.Core.CompilerServices.ArrayCollector`1[T]: Void AddMany(System.Collections.Generic.IEnumerable`1[T]) @@ -723,6 +771,11 @@ Microsoft.FSharp.Core.CompilerServices.IProvidedNamespace: System.String Namespa Microsoft.FSharp.Core.CompilerServices.IProvidedNamespace: System.String get_NamespaceName() Microsoft.FSharp.Core.CompilerServices.IProvidedNamespace: System.Type ResolveTypeName(System.String) Microsoft.FSharp.Core.CompilerServices.IProvidedNamespace: System.Type[] GetTypes() +Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1[TData]: Int32 ResumptionPoint +Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1[TData]: Int32 get_ResumptionPoint() +Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1[TData]: TData Data +Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1[TData]: TData get_Data() +Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1[TData]: Void set_Data(TData) Microsoft.FSharp.Core.CompilerServices.ITypeProvider2: System.Reflection.MethodBase ApplyStaticArgumentsForMethod(System.Reflection.MethodBase, System.String, System.Object[]) Microsoft.FSharp.Core.CompilerServices.ITypeProvider2: System.Reflection.ParameterInfo[] GetStaticParametersForMethod(System.Reflection.MethodBase) Microsoft.FSharp.Core.CompilerServices.ITypeProvider: Byte[] GetGeneratedAssemblyContents(System.Reflection.Assembly) @@ -733,11 +786,58 @@ Microsoft.FSharp.Core.CompilerServices.ITypeProvider: System.Reflection.Paramete Microsoft.FSharp.Core.CompilerServices.ITypeProvider: System.Type ApplyStaticArguments(System.Type, System.String[], System.Object[]) Microsoft.FSharp.Core.CompilerServices.ITypeProvider: Void add_Invalidate(System.EventHandler) Microsoft.FSharp.Core.CompilerServices.ITypeProvider: Void remove_Invalidate(System.EventHandler) +Microsoft.FSharp.Core.CompilerServices.MoveNextMethodImpl`1[TData]: System.IAsyncResult BeginInvoke(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef, System.AsyncCallback, System.Object) +Microsoft.FSharp.Core.CompilerServices.MoveNextMethodImpl`1[TData]: Void .ctor(System.Object, IntPtr) +Microsoft.FSharp.Core.CompilerServices.MoveNextMethodImpl`1[TData]: Void EndInvoke(System.IAsyncResult) +Microsoft.FSharp.Core.CompilerServices.MoveNextMethodImpl`1[TData]: Void Invoke(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Boolean CombineDynamic[TData,T](Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef, Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Boolean TryFinallyAsyncDynamic[TData,T](Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef, Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T], Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Boolean TryWithDynamic[TData,T](Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef, Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T], Microsoft.FSharp.Core.FSharpFunc`2[System.Exception,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T]]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Boolean WhileDynamic[TData](Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Boolean], Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Boolean YieldDynamic[TData](Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit] For[T,TData](System.Collections.Generic.IEnumerable`1[T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit]]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit] While[TData](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Boolean], Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit] Yield[TData]() +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit] Zero[TData]() +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T] Combine[TData,T](Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T] Delay[TData,T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T]]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T] TryFinallyAsync[TData,T](Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T], Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T] TryFinally[TData,T](Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T], Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,Microsoft.FSharp.Core.Unit]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T] TryWith[TData,T](Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T], Microsoft.FSharp.Core.FSharpFunc`2[System.Exception,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T]]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T] Using[TResource,TData,T](TResource, Microsoft.FSharp.Core.FSharpFunc`2[TResource,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T]]) +Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T]: Boolean EndInvoke(System.IAsyncResult) +Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T]: Boolean Invoke(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef) +Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T]: System.IAsyncResult BeginInvoke(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef, System.AsyncCallback, System.Object) +Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[TData,T]: Void .ctor(System.Object, IntPtr) +Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData]: Int32 ResumptionPoint +Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData]: Microsoft.FSharp.Core.CompilerServices.ResumptionDynamicInfo`1[TData] ResumptionDynamicInfo +Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData]: TData Data +Microsoft.FSharp.Core.CompilerServices.ResumptionDynamicInfo`1[TData]: Microsoft.FSharp.Core.CompilerServices.ResumptionFunc`1[TData] ResumptionFunc +Microsoft.FSharp.Core.CompilerServices.ResumptionDynamicInfo`1[TData]: Microsoft.FSharp.Core.CompilerServices.ResumptionFunc`1[TData] get_ResumptionFunc() +Microsoft.FSharp.Core.CompilerServices.ResumptionDynamicInfo`1[TData]: System.Object ResumptionData +Microsoft.FSharp.Core.CompilerServices.ResumptionDynamicInfo`1[TData]: System.Object get_ResumptionData() +Microsoft.FSharp.Core.CompilerServices.ResumptionDynamicInfo`1[TData]: Void .ctor(Microsoft.FSharp.Core.CompilerServices.ResumptionFunc`1[TData]) +Microsoft.FSharp.Core.CompilerServices.ResumptionDynamicInfo`1[TData]: Void MoveNext(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef) +Microsoft.FSharp.Core.CompilerServices.ResumptionDynamicInfo`1[TData]: Void SetStateMachine(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef, System.Runtime.CompilerServices.IAsyncStateMachine) +Microsoft.FSharp.Core.CompilerServices.ResumptionDynamicInfo`1[TData]: Void set_ResumptionData(System.Object) +Microsoft.FSharp.Core.CompilerServices.ResumptionDynamicInfo`1[TData]: Void set_ResumptionFunc(Microsoft.FSharp.Core.CompilerServices.ResumptionFunc`1[TData]) +Microsoft.FSharp.Core.CompilerServices.ResumptionFunc`1[TData]: Boolean EndInvoke(System.IAsyncResult) +Microsoft.FSharp.Core.CompilerServices.ResumptionFunc`1[TData]: Boolean Invoke(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef) +Microsoft.FSharp.Core.CompilerServices.ResumptionFunc`1[TData]: System.IAsyncResult BeginInvoke(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef, System.AsyncCallback, System.Object) +Microsoft.FSharp.Core.CompilerServices.ResumptionFunc`1[TData]: Void .ctor(System.Object, IntPtr) Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers: Microsoft.FSharp.Control.IEvent`2[TDelegate,TArgs] CreateEvent[TDelegate,TArgs](Microsoft.FSharp.Core.FSharpFunc`2[TDelegate,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpFunc`2[TDelegate,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.FSharpFunc`2[System.Object,Microsoft.FSharp.Core.FSharpFunc`2[TArgs,Microsoft.FSharp.Core.Unit]],TDelegate]) Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers: System.Collections.Generic.IEnumerable`1[TResult] EnumerateFromFunctions[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]) Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers: System.Collections.Generic.IEnumerable`1[TResult] EnumerateUsing[T,TCollection,TResult](T, Microsoft.FSharp.Core.FSharpFunc`2[T,TCollection]) Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers: System.Collections.Generic.IEnumerable`1[T] EnumerateThenFinally[T](System.Collections.Generic.IEnumerable`1[T], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit]) Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers: System.Collections.Generic.IEnumerable`1[T] EnumerateWhile[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,System.Boolean], System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Core.CompilerServices.SetStateMachineMethodImpl`1[TData]: System.IAsyncResult BeginInvoke(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef, System.Runtime.CompilerServices.IAsyncStateMachine, System.AsyncCallback, System.Object) +Microsoft.FSharp.Core.CompilerServices.SetStateMachineMethodImpl`1[TData]: Void .ctor(System.Object, IntPtr) +Microsoft.FSharp.Core.CompilerServices.SetStateMachineMethodImpl`1[TData]: Void EndInvoke(System.IAsyncResult) +Microsoft.FSharp.Core.CompilerServices.SetStateMachineMethodImpl`1[TData]: Void Invoke(Microsoft.FSharp.Core.CompilerServices.ResumableStateMachine`1[TData] ByRef, System.Runtime.CompilerServices.IAsyncStateMachine) +Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers: Boolean __useResumableCode[T]() +Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers: Microsoft.FSharp.Core.FSharpOption`1[System.Int32] __resumableEntry() +Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers: T __resumeAt[T](Int32) +Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers: TResult __stateMachine[TData,TResult](Microsoft.FSharp.Core.CompilerServices.MoveNextMethodImpl`1[TData], Microsoft.FSharp.Core.CompilerServices.SetStateMachineMethodImpl`1[TData], Microsoft.FSharp.Core.CompilerServices.AfterCode`2[TData,TResult]) Microsoft.FSharp.Core.CompilerServices.TypeProviderAssemblyAttribute: System.String AssemblyName Microsoft.FSharp.Core.CompilerServices.TypeProviderAssemblyAttribute: System.String get_AssemblyName() Microsoft.FSharp.Core.CompilerServices.TypeProviderAssemblyAttribute: Void .ctor() @@ -821,9 +921,13 @@ Microsoft.FSharp.Core.EqualityConditionalOnAttribute: Void .ctor() Microsoft.FSharp.Core.ExperimentalAttribute: System.String Message Microsoft.FSharp.Core.ExperimentalAttribute: System.String get_Message() Microsoft.FSharp.Core.ExperimentalAttribute: Void .ctor(System.String) +Microsoft.FSharp.Core.ExtraTopLevelOperators+Checked: Byte ToByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], T) Microsoft.FSharp.Core.ExtraTopLevelOperators+Checked: Byte ToByte[T](T) +Microsoft.FSharp.Core.ExtraTopLevelOperators+Checked: SByte ToSByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], T) Microsoft.FSharp.Core.ExtraTopLevelOperators+Checked: SByte ToSByte[T](T) +Microsoft.FSharp.Core.ExtraTopLevelOperators: Byte ToByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], T) Microsoft.FSharp.Core.ExtraTopLevelOperators: Byte ToByte[T](T) +Microsoft.FSharp.Core.ExtraTopLevelOperators: Double ToDouble$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Double], T) Microsoft.FSharp.Core.ExtraTopLevelOperators: Double ToDouble[T](T) Microsoft.FSharp.Core.ExtraTopLevelOperators: Microsoft.FSharp.Collections.FSharpSet`1[T] CreateSet[T](System.Collections.Generic.IEnumerable`1[T]) Microsoft.FSharp.Core.ExtraTopLevelOperators: Microsoft.FSharp.Control.FSharpAsyncBuilder DefaultAsyncBuilder @@ -831,7 +935,9 @@ Microsoft.FSharp.Core.ExtraTopLevelOperators: Microsoft.FSharp.Control.FSharpAsy Microsoft.FSharp.Core.ExtraTopLevelOperators: Microsoft.FSharp.Core.ExtraTopLevelOperators+Checked Microsoft.FSharp.Core.ExtraTopLevelOperators: Microsoft.FSharp.Linq.QueryBuilder get_query() Microsoft.FSharp.Core.ExtraTopLevelOperators: Microsoft.FSharp.Linq.QueryBuilder query +Microsoft.FSharp.Core.ExtraTopLevelOperators: SByte ToSByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], T) Microsoft.FSharp.Core.ExtraTopLevelOperators: SByte ToSByte[T](T) +Microsoft.FSharp.Core.ExtraTopLevelOperators: Single ToSingle$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Single], T) Microsoft.FSharp.Core.ExtraTopLevelOperators: Single ToSingle[T](T) Microsoft.FSharp.Core.ExtraTopLevelOperators: System.Collections.Generic.IDictionary`2[TKey,TValue] CreateDictionary[TKey,TValue](System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,TValue]]) Microsoft.FSharp.Core.ExtraTopLevelOperators: System.Collections.Generic.IReadOnlyDictionary`2[TKey,TValue] CreateReadOnlyDictionary[TKey,TValue](System.Collections.Generic.IEnumerable`1[System.Tuple`2[TKey,TValue]]) @@ -847,36 +953,8 @@ Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormat[T](Microsoft.FSharp. Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceExpression[T](Microsoft.FSharp.Quotations.FSharpExpr`1[T]) Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceUntypedExpression[T](Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Core.ExtraTopLevelOperators: T[,] CreateArray2D[?,T](System.Collections.Generic.IEnumerable`1[?]) -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`2[T1,T2]) -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Boolean IsChoice1Of2 -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Boolean IsChoice2Of2 -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Boolean get_IsChoice1Of2() -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Boolean get_IsChoice2Of2() -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`2[T1,T2]) -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: T1 Item Microsoft.FSharp.Core.FSharpChoice`2+Choice1Of2[T1,T2]: T1 get_Item() -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`2[T1,T2]) -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Boolean IsChoice1Of2 -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Boolean IsChoice2Of2 -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Boolean get_IsChoice1Of2() -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Boolean get_IsChoice2Of2() -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`2[T1,T2]) -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: T2 Item Microsoft.FSharp.Core.FSharpChoice`2+Choice2Of2[T1,T2]: T2 get_Item() Microsoft.FSharp.Core.FSharpChoice`2+Tags[T1,T2]: Int32 Choice1Of2 @@ -900,58 +978,10 @@ Microsoft.FSharp.Core.FSharpChoice`2[T1,T2]: Microsoft.FSharp.Core.FSharpChoice` Microsoft.FSharp.Core.FSharpChoice`2[T1,T2]: Microsoft.FSharp.Core.FSharpChoice`2+Tags[T1,T2] Microsoft.FSharp.Core.FSharpChoice`2[T1,T2]: Microsoft.FSharp.Core.FSharpChoice`2[T1,T2] NewChoice1Of2(T1) Microsoft.FSharp.Core.FSharpChoice`2[T1,T2]: Microsoft.FSharp.Core.FSharpChoice`2[T1,T2] NewChoice2Of2(T2) -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3]) -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Boolean IsChoice1Of3 -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Boolean IsChoice2Of3 -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Boolean IsChoice3Of3 -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Boolean get_IsChoice1Of3() -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Boolean get_IsChoice2Of3() -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Boolean get_IsChoice3Of3() -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3]) -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: T1 Item Microsoft.FSharp.Core.FSharpChoice`3+Choice1Of3[T1,T2,T3]: T1 get_Item() -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3]) -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Boolean IsChoice1Of3 -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Boolean IsChoice2Of3 -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Boolean IsChoice3Of3 -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Boolean get_IsChoice1Of3() -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Boolean get_IsChoice2Of3() -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Boolean get_IsChoice3Of3() -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3]) -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: T2 Item Microsoft.FSharp.Core.FSharpChoice`3+Choice2Of3[T1,T2,T3]: T2 get_Item() -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3]) -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Boolean IsChoice1Of3 -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Boolean IsChoice2Of3 -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Boolean IsChoice3Of3 -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Boolean get_IsChoice1Of3() -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Boolean get_IsChoice2Of3() -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Boolean get_IsChoice3Of3() -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3]) -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: T3 Item Microsoft.FSharp.Core.FSharpChoice`3+Choice3Of3[T1,T2,T3]: T3 get_Item() Microsoft.FSharp.Core.FSharpChoice`3+Tags[T1,T2,T3]: Int32 Choice1Of3 @@ -980,84 +1010,12 @@ Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3]: Microsoft.FSharp.Core.FSharpChoi Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3]: Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3] NewChoice1Of3(T1) Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3]: Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3] NewChoice2Of3(T2) Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3]: Microsoft.FSharp.Core.FSharpChoice`3[T1,T2,T3] NewChoice3Of3(T3) -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]) -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Boolean IsChoice1Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Boolean IsChoice2Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Boolean IsChoice3Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Boolean IsChoice4Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Boolean get_IsChoice1Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Boolean get_IsChoice2Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Boolean get_IsChoice3Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Boolean get_IsChoice4Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]) -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: T1 Item Microsoft.FSharp.Core.FSharpChoice`4+Choice1Of4[T1,T2,T3,T4]: T1 get_Item() -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]) -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Boolean IsChoice1Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Boolean IsChoice2Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Boolean IsChoice3Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Boolean IsChoice4Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Boolean get_IsChoice1Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Boolean get_IsChoice2Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Boolean get_IsChoice3Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Boolean get_IsChoice4Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]) -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: T2 Item Microsoft.FSharp.Core.FSharpChoice`4+Choice2Of4[T1,T2,T3,T4]: T2 get_Item() -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]) -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Boolean IsChoice1Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Boolean IsChoice2Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Boolean IsChoice3Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Boolean IsChoice4Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Boolean get_IsChoice1Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Boolean get_IsChoice2Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Boolean get_IsChoice3Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Boolean get_IsChoice4Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]) -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: T3 Item Microsoft.FSharp.Core.FSharpChoice`4+Choice3Of4[T1,T2,T3,T4]: T3 get_Item() -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]) -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Boolean IsChoice1Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Boolean IsChoice2Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Boolean IsChoice3Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Boolean IsChoice4Of4 -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Boolean get_IsChoice1Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Boolean get_IsChoice2Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Boolean get_IsChoice3Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Boolean get_IsChoice4Of4() -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]) -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: T4 Item Microsoft.FSharp.Core.FSharpChoice`4+Choice4Of4[T1,T2,T3,T4]: T4 get_Item() Microsoft.FSharp.Core.FSharpChoice`4+Tags[T1,T2,T3,T4]: Int32 Choice1Of4 @@ -1091,114 +1049,14 @@ Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]: Microsoft.FSharp.Core.FSharpC Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]: Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4] NewChoice2Of4(T2) Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]: Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4] NewChoice3Of4(T3) Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4]: Microsoft.FSharp.Core.FSharpChoice`4[T1,T2,T3,T4] NewChoice4Of4(T4) -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]) -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean IsChoice1Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean IsChoice2Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean IsChoice3Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean IsChoice4Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean IsChoice5Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice1Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice2Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice3Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice4Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice5Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]) -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: T1 Item Microsoft.FSharp.Core.FSharpChoice`5+Choice1Of5[T1,T2,T3,T4,T5]: T1 get_Item() -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]) -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean IsChoice1Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean IsChoice2Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean IsChoice3Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean IsChoice4Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean IsChoice5Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice1Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice2Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice3Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice4Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice5Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]) -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: T2 Item Microsoft.FSharp.Core.FSharpChoice`5+Choice2Of5[T1,T2,T3,T4,T5]: T2 get_Item() -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]) -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean IsChoice1Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean IsChoice2Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean IsChoice3Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean IsChoice4Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean IsChoice5Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice1Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice2Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice3Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice4Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice5Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]) -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: T3 Item Microsoft.FSharp.Core.FSharpChoice`5+Choice3Of5[T1,T2,T3,T4,T5]: T3 get_Item() -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]) -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean IsChoice1Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean IsChoice2Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean IsChoice3Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean IsChoice4Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean IsChoice5Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice1Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice2Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice3Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice4Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice5Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]) -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: T4 Item Microsoft.FSharp.Core.FSharpChoice`5+Choice4Of5[T1,T2,T3,T4,T5]: T4 get_Item() -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]) -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean IsChoice1Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean IsChoice2Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean IsChoice3Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean IsChoice4Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean IsChoice5Of5 -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice1Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice2Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice3Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice4Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Boolean get_IsChoice5Of5() -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]) -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: T5 Item Microsoft.FSharp.Core.FSharpChoice`5+Choice5Of5[T1,T2,T3,T4,T5]: T5 get_Item() Microsoft.FSharp.Core.FSharpChoice`5+Tags[T1,T2,T3,T4,T5]: Int32 Choice1Of5 @@ -1237,148 +1095,16 @@ Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]: Microsoft.FSharp.Core.FSha Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]: Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5] NewChoice3Of5(T3) Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]: Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5] NewChoice4Of5(T4) Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5]: Microsoft.FSharp.Core.FSharpChoice`5[T1,T2,T3,T4,T5] NewChoice5Of5(T5) -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice1Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice2Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice3Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice4Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice5Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice6Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice1Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice2Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice3Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice4Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice5Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice6Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: T1 Item Microsoft.FSharp.Core.FSharpChoice`6+Choice1Of6[T1,T2,T3,T4,T5,T6]: T1 get_Item() -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice1Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice2Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice3Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice4Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice5Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice6Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice1Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice2Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice3Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice4Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice5Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice6Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: T2 Item Microsoft.FSharp.Core.FSharpChoice`6+Choice2Of6[T1,T2,T3,T4,T5,T6]: T2 get_Item() -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice1Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice2Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice3Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice4Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice5Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice6Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice1Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice2Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice3Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice4Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice5Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice6Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: T3 Item Microsoft.FSharp.Core.FSharpChoice`6+Choice3Of6[T1,T2,T3,T4,T5,T6]: T3 get_Item() -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice1Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice2Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice3Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice4Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice5Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice6Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice1Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice2Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice3Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice4Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice5Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice6Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: T4 Item Microsoft.FSharp.Core.FSharpChoice`6+Choice4Of6[T1,T2,T3,T4,T5,T6]: T4 get_Item() -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice1Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice2Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice3Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice4Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice5Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice6Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice1Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice2Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice3Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice4Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice5Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice6Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: T5 Item Microsoft.FSharp.Core.FSharpChoice`6+Choice5Of6[T1,T2,T3,T4,T5,T6]: T5 get_Item() -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice1Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice2Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice3Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice4Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice5Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean IsChoice6Of6 -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice1Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice2Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice3Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice4Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice5Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Boolean get_IsChoice6Of6() -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]) -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: T6 Item Microsoft.FSharp.Core.FSharpChoice`6+Choice6Of6[T1,T2,T3,T4,T5,T6]: T6 get_Item() Microsoft.FSharp.Core.FSharpChoice`6+Tags[T1,T2,T3,T4,T5,T6]: Int32 Choice1Of6 @@ -1422,186 +1148,18 @@ Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]: Microsoft.FSharp.Core.F Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]: Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6] NewChoice4Of6(T4) Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]: Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6] NewChoice5Of6(T5) Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6]: Microsoft.FSharp.Core.FSharpChoice`6[T1,T2,T3,T4,T5,T6] NewChoice6Of6(T6) -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice1Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice2Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice3Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice4Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice5Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice6Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice7Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice1Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice2Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice3Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice4Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice5Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice6Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice7Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: T1 Item Microsoft.FSharp.Core.FSharpChoice`7+Choice1Of7[T1,T2,T3,T4,T5,T6,T7]: T1 get_Item() -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice1Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice2Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice3Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice4Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice5Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice6Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice7Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice1Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice2Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice3Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice4Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice5Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice6Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice7Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: T2 Item Microsoft.FSharp.Core.FSharpChoice`7+Choice2Of7[T1,T2,T3,T4,T5,T6,T7]: T2 get_Item() -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice1Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice2Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice3Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice4Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice5Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice6Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice7Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice1Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice2Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice3Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice4Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice5Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice6Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice7Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: T3 Item Microsoft.FSharp.Core.FSharpChoice`7+Choice3Of7[T1,T2,T3,T4,T5,T6,T7]: T3 get_Item() -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice1Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice2Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice3Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice4Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice5Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice6Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice7Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice1Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice2Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice3Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice4Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice5Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice6Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice7Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: T4 Item Microsoft.FSharp.Core.FSharpChoice`7+Choice4Of7[T1,T2,T3,T4,T5,T6,T7]: T4 get_Item() -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice1Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice2Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice3Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice4Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice5Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice6Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice7Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice1Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice2Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice3Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice4Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice5Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice6Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice7Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: T5 Item Microsoft.FSharp.Core.FSharpChoice`7+Choice5Of7[T1,T2,T3,T4,T5,T6,T7]: T5 get_Item() -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice1Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice2Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice3Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice4Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice5Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice6Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice7Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice1Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice2Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice3Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice4Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice5Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice6Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice7Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: T6 Item Microsoft.FSharp.Core.FSharpChoice`7+Choice6Of7[T1,T2,T3,T4,T5,T6,T7]: T6 get_Item() -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean Equals(System.Object, System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice1Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice2Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice3Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice4Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice5Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice6Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean IsChoice7Of7 -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice1Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice2Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice3Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice4Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice5Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice6Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Boolean get_IsChoice7Of7() -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(Microsoft.FSharp.Core.FSharpChoice`7[T1,T2,T3,T4,T5,T6,T7]) -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object) -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 CompareTo(System.Object, System.Collections.IComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode() -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 GetHashCode(System.Collections.IEqualityComparer) -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 Tag -Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: Int32 get_Tag() Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: T7 Item Microsoft.FSharp.Core.FSharpChoice`7+Choice7Of7[T1,T2,T3,T4,T5,T6,T7]: T7 get_Item() Microsoft.FSharp.Core.FSharpChoice`7+Tags[T1,T2,T3,T4,T5,T6,T7]: Int32 Choice1Of7 @@ -1784,6 +1342,7 @@ Microsoft.FSharp.Core.FuncConvert: Microsoft.FSharp.Core.FSharpFunc`2[T1,Microso Microsoft.FSharp.Core.FuncConvert: Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]] FromFunc[T1,T2,TResult](System.Func`3[T1,T2,TResult]) Microsoft.FSharp.Core.FuncConvert: Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]] FuncFromTupled[T1,T2,TResult](Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[T1,T2],TResult]) Microsoft.FSharp.Core.GeneralizableValueAttribute: Void .ctor() +Microsoft.FSharp.Core.InlineIfLambdaAttribute: Void .ctor() Microsoft.FSharp.Core.InterfaceAttribute: Void .ctor() Microsoft.FSharp.Core.LanguagePrimitives+ErrorStrings: System.String AddressOpNotFirstClassString Microsoft.FSharp.Core.LanguagePrimitives+ErrorStrings: System.String InputArrayEmptyString @@ -1886,24 +1445,46 @@ Microsoft.FSharp.Core.LanguagePrimitives: System.Collections.IEqualityComparer G Microsoft.FSharp.Core.LanguagePrimitives: System.Collections.IEqualityComparer get_GenericEqualityComparer() Microsoft.FSharp.Core.LanguagePrimitives: System.Collections.IEqualityComparer get_GenericEqualityERComparer() Microsoft.FSharp.Core.LanguagePrimitives: System.Decimal DecimalWithMeasure(System.Decimal) +Microsoft.FSharp.Core.LanguagePrimitives: T DivideByInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], T, Int32) Microsoft.FSharp.Core.LanguagePrimitives: T DivideByIntDynamic[T](T, Int32) Microsoft.FSharp.Core.LanguagePrimitives: T DivideByInt[T](T, Int32) Microsoft.FSharp.Core.LanguagePrimitives: T EnumToValue[TEnum,T](TEnum) Microsoft.FSharp.Core.LanguagePrimitives: T GenericMaximum[T](T, T) Microsoft.FSharp.Core.LanguagePrimitives: T GenericMinimum[T](T, T) +Microsoft.FSharp.Core.LanguagePrimitives: T GenericOne$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T]) Microsoft.FSharp.Core.LanguagePrimitives: T GenericOneDynamic[T]() Microsoft.FSharp.Core.LanguagePrimitives: T GenericOne[T]() +Microsoft.FSharp.Core.LanguagePrimitives: T GenericZero$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T]) Microsoft.FSharp.Core.LanguagePrimitives: T GenericZeroDynamic[T]() Microsoft.FSharp.Core.LanguagePrimitives: T GenericZero[T]() Microsoft.FSharp.Core.LanguagePrimitives: TEnum EnumOfValue[T,TEnum](T) Microsoft.FSharp.Core.LanguagePrimitives: TResult AdditionDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult BitwiseAndDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult BitwiseOrDynamic[T1,T2,TResult](T1, T2) Microsoft.FSharp.Core.LanguagePrimitives: TResult CheckedAdditionDynamic[T1,T2,TResult](T1, T2) Microsoft.FSharp.Core.LanguagePrimitives: TResult CheckedMultiplyDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult CheckedSubtractionDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult CheckedUnaryNegationDynamic[T,TResult](T) +Microsoft.FSharp.Core.LanguagePrimitives: TResult DivisionDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult EqualityDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult ExclusiveOrDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult ExplicitDynamic[T,TResult](T) +Microsoft.FSharp.Core.LanguagePrimitives: TResult GreaterThanDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult GreaterThanOrEqualDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult InequalityDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult LeftShiftDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult LessThanDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult LessThanOrEqualDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult LogicalNotDynamic[T,TResult](T) +Microsoft.FSharp.Core.LanguagePrimitives: TResult ModulusDynamic[T1,T2,TResult](T1, T2) Microsoft.FSharp.Core.LanguagePrimitives: TResult MultiplyDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: UInt32 ParseUInt32(System.String) -Microsoft.FSharp.Core.LanguagePrimitives: UInt64 ParseUInt64(System.String) +Microsoft.FSharp.Core.LanguagePrimitives: TResult RightShiftDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult SubtractionDynamic[T1,T2,TResult](T1, T2) +Microsoft.FSharp.Core.LanguagePrimitives: TResult UnaryNegationDynamic[T,TResult](T) Microsoft.FSharp.Core.LanguagePrimitives: UInt16 UInt16WithMeasure(UInt16) +Microsoft.FSharp.Core.LanguagePrimitives: UInt32 ParseUInt32(System.String) Microsoft.FSharp.Core.LanguagePrimitives: UInt32 UInt32WithMeasure(UInt32) +Microsoft.FSharp.Core.LanguagePrimitives: UInt64 ParseUInt64(System.String) Microsoft.FSharp.Core.LanguagePrimitives: UInt64 UInt64WithMeasure(UInt64) Microsoft.FSharp.Core.LanguagePrimitives: UIntPtr UIntPtrWithMeasure(UIntPtr) Microsoft.FSharp.Core.LiteralAttribute: Void .ctor() @@ -1939,31 +1520,56 @@ Microsoft.FSharp.Core.Operators+ArrayExtensions: Int32 [,,,]`1.GetReverseIndex[T Microsoft.FSharp.Core.Operators+ArrayExtensions: Int32 [,,]`1.GetReverseIndex[T](T[,,], Int32, Int32) Microsoft.FSharp.Core.Operators+ArrayExtensions: Int32 [,]`1.GetReverseIndex[T](T[,], Int32, Int32) Microsoft.FSharp.Core.Operators+ArrayExtensions: Int32 []`1.GetReverseIndex[T](T[], Int32, Int32) +Microsoft.FSharp.Core.Operators+Checked: Byte ToByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], T) Microsoft.FSharp.Core.Operators+Checked: Byte ToByte[T](T) +Microsoft.FSharp.Core.Operators+Checked: Char ToChar$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Char], T) Microsoft.FSharp.Core.Operators+Checked: Char ToChar[T](T) +Microsoft.FSharp.Core.Operators+Checked: Int16 ToInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int16], T) Microsoft.FSharp.Core.Operators+Checked: Int16 ToInt16[T](T) +Microsoft.FSharp.Core.Operators+Checked: Int32 ToInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], T) +Microsoft.FSharp.Core.Operators+Checked: Int32 ToInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], T) Microsoft.FSharp.Core.Operators+Checked: Int32 ToInt32[T](T) Microsoft.FSharp.Core.Operators+Checked: Int32 ToInt[T](T) +Microsoft.FSharp.Core.Operators+Checked: Int64 ToInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int64], T) Microsoft.FSharp.Core.Operators+Checked: Int64 ToInt64[T](T) +Microsoft.FSharp.Core.Operators+Checked: IntPtr ToIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.IntPtr], T) Microsoft.FSharp.Core.Operators+Checked: IntPtr ToIntPtr[T](T) +Microsoft.FSharp.Core.Operators+Checked: SByte ToSByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], T) Microsoft.FSharp.Core.Operators+Checked: SByte ToSByte[T](T) +Microsoft.FSharp.Core.Operators+Checked: T op_UnaryNegation$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators+Checked: T op_UnaryNegation[T](T) +Microsoft.FSharp.Core.Operators+Checked: T3 op_Addition$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) Microsoft.FSharp.Core.Operators+Checked: T3 op_Addition[T1,T2,T3](T1, T2) +Microsoft.FSharp.Core.Operators+Checked: T3 op_Multiply$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) Microsoft.FSharp.Core.Operators+Checked: T3 op_Multiply[T1,T2,T3](T1, T2) +Microsoft.FSharp.Core.Operators+Checked: T3 op_Subtraction$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) Microsoft.FSharp.Core.Operators+Checked: T3 op_Subtraction[T1,T2,T3](T1, T2) +Microsoft.FSharp.Core.Operators+Checked: UInt16 ToUInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt16], T) Microsoft.FSharp.Core.Operators+Checked: UInt16 ToUInt16[T](T) +Microsoft.FSharp.Core.Operators+Checked: UInt32 ToUInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt32], T) Microsoft.FSharp.Core.Operators+Checked: UInt32 ToUInt32[T](T) +Microsoft.FSharp.Core.Operators+Checked: UInt64 ToUInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt64], T) Microsoft.FSharp.Core.Operators+Checked: UInt64 ToUInt64[T](T) +Microsoft.FSharp.Core.Operators+Checked: UIntPtr ToUIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UIntPtr], T) Microsoft.FSharp.Core.Operators+Checked: UIntPtr ToUIntPtr[T](T) +Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_Equality$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], T, T) Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_Equality[T](T, T) +Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_GreaterThan$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], T, TResult) +Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_GreaterThanOrEqual$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], T, TResult) Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_GreaterThanOrEqual[T,TResult](T, TResult) Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_GreaterThan[T,TResult](T, TResult) +Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_Inequality$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], T, T) Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_Inequality[T](T, T) +Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_LessThan$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], T, TResult) +Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_LessThanOrEqual$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], T, TResult) Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_LessThanOrEqual[T,TResult](T, TResult) Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_LessThan[T,TResult](T, TResult) +Microsoft.FSharp.Core.Operators+NonStructuralComparison: Int32 Compare$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], T, T) Microsoft.FSharp.Core.Operators+NonStructuralComparison: Int32 Compare[T](T, T) Microsoft.FSharp.Core.Operators+NonStructuralComparison: Int32 Hash[T](T) +Microsoft.FSharp.Core.Operators+NonStructuralComparison: T Max$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], T, T) Microsoft.FSharp.Core.Operators+NonStructuralComparison: T Max[T](T, T) +Microsoft.FSharp.Core.Operators+NonStructuralComparison: T Min$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], T, T) Microsoft.FSharp.Core.Operators+NonStructuralComparison: T Min[T](T, T) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Byte PowByte(Byte, Int32) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Double PowDouble(Double, Int32) @@ -2014,15 +1620,29 @@ Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T2 Atan2Dynamic[T1,T2](T1, T Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T2 SqrtDynamic[T1,T2](T1) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,,,] GetArraySlice4D[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,,] GetArraySlice3D[T](T[,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,,] GetArraySlice4DFixedSingle1[T](T[,,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,,] GetArraySlice4DFixedSingle2[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,,] GetArraySlice4DFixedSingle3[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,,] GetArraySlice4DFixedSingle4[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice2D[T](T[,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice3DFixedSingle1[T](T[,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice3DFixedSingle2[T](T[,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice3DFixedSingle3[T](T[,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble1[T](T[,,,], Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble2[T](T[,,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble3[T](T[,,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble4[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble5[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble6[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Int32) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice2DFixed1[T](T[,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice2DFixed2[T](T[,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice3DFixedDouble1[T](T[,,], Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice3DFixedDouble2[T](T[,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice3DFixedDouble3[T](T[,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Int32) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice2D[T](T[,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice2DFixed1[T](T[,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice2DFixed2[T](T[,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice4DFixedTriple1[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Int32, Int32) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice4DFixedTriple2[T](T[,,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Int32) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice4DFixedTriple3[T](T[,,,], Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice4DFixedTriple4[T](T[,,,], Int32, Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice[T](T[], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: UInt16 PowUInt16(UInt16, Int32) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: UInt32 PowUInt32(UInt32, Int32) @@ -2031,28 +1651,13 @@ Microsoft.FSharp.Core.Operators+OperatorIntrinsics: UIntPtr PowUIntPtr(UIntPtr, Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice2DFixed1[T](T[,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice2DFixed2[T](T[,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, T[]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice2D[T](T[,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[,]) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice3D[T](T[,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[,,]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice3DFixedDouble1[T](T[,,], Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice3DFixedDouble2[T](T[,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, T[]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice3DFixedDouble3[T](T[,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Int32, T[]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice3DFixedSingle1[T](T[,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[,]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice3DFixedSingle2[T](T[,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[,]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice3DFixedSingle3[T](T[,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, T[,]) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice4D[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[,,,]) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,,] GetArraySlice4DFixedSingle1[T](T[,,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,,] GetArraySlice4DFixedSingle2[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,,] GetArraySlice4DFixedSingle3[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,,] GetArraySlice4DFixedSingle4[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble1[T](T[,,,], Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble2[T](T[,,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble3[T](T[,,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble4[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble5[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[,] GetArraySlice4DFixedDouble6[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Int32) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice4DFixedTriple1[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Int32, Int32) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice4DFixedTriple2[T](T[,,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Int32) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice4DFixedTriple3[T](T[,,,], Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32) -Microsoft.FSharp.Core.Operators+OperatorIntrinsics: T[] GetArraySlice4DFixedTriple4[T](T[,,,], Int32, Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32]) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice3D[T](T[,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[,,]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice4DFixedDouble1[T](T[,,,], Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[,]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice4DFixedDouble2[T](T[,,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[,]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice4DFixedDouble3[T](T[,,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, T[,]) @@ -2067,6 +1672,7 @@ Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice4DFixedTri Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice4DFixedTriple2[T](T[,,,], Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, Int32, T[]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice4DFixedTriple3[T](T[,,,], Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Int32, T[]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice4DFixedTriple4[T](T[,,,], Int32, Int32, Int32, Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[]) +Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice4D[T](T[,,,], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[,,,]) Microsoft.FSharp.Core.Operators+OperatorIntrinsics: Void SetArraySlice[T](T[], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], Microsoft.FSharp.Core.FSharpOption`1[System.Int32], T[]) Microsoft.FSharp.Core.Operators+Unchecked: Boolean Equals[T](T, T) Microsoft.FSharp.Core.Operators+Unchecked: Int32 Compare[T](T, T) @@ -2081,23 +1687,31 @@ Microsoft.FSharp.Core.Operators: Boolean op_GreaterThan[T](T, T) Microsoft.FSharp.Core.Operators: Boolean op_Inequality[T](T, T) Microsoft.FSharp.Core.Operators: Boolean op_LessThanOrEqual[T](T, T) Microsoft.FSharp.Core.Operators: Boolean op_LessThan[T](T, T) +Microsoft.FSharp.Core.Operators: Byte ToByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], T) Microsoft.FSharp.Core.Operators: Byte ToByte[T](T) +Microsoft.FSharp.Core.Operators: Char ToChar$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Char], T) Microsoft.FSharp.Core.Operators: Char ToChar[T](T) Microsoft.FSharp.Core.Operators: Double Infinity Microsoft.FSharp.Core.Operators: Double NaN +Microsoft.FSharp.Core.Operators: Double ToDouble$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Double], T) Microsoft.FSharp.Core.Operators: Double ToDouble[T](T) Microsoft.FSharp.Core.Operators: Double get_Infinity() Microsoft.FSharp.Core.Operators: Double get_NaN() +Microsoft.FSharp.Core.Operators: Int16 ToInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int16], T) Microsoft.FSharp.Core.Operators: Int16 ToInt16[T](T) Microsoft.FSharp.Core.Operators: Int32 Compare[T](T, T) Microsoft.FSharp.Core.Operators: Int32 Hash[T](T) +Microsoft.FSharp.Core.Operators: Int32 Sign$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], T) Microsoft.FSharp.Core.Operators: Int32 Sign[T](T) Microsoft.FSharp.Core.Operators: Int32 SizeOf[T]() +Microsoft.FSharp.Core.Operators: Int32 ToInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], T) +Microsoft.FSharp.Core.Operators: Int32 ToInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], T) Microsoft.FSharp.Core.Operators: Int32 ToInt32[T](T) Microsoft.FSharp.Core.Operators: Int32 ToInt[T](T) -Microsoft.FSharp.Core.Operators: UInt32 ToUInt[T](T) Microsoft.FSharp.Core.Operators: Int32 limitedHash[T](Int32, T) +Microsoft.FSharp.Core.Operators: Int64 ToInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int64], T) Microsoft.FSharp.Core.Operators: Int64 ToInt64[T](T) +Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.IntPtr], T) Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr[T](T) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Collections.FSharpList`1[T] op_Append[T](Microsoft.FSharp.Collections.FSharpList`1[T], Microsoft.FSharp.Collections.FSharpList`1[T]) Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.FSharpFunc`2[T1,T3] op_ComposeLeft[T2,T3,T1](Microsoft.FSharp.Core.FSharpFunc`2[T2,T3], Microsoft.FSharp.Core.FSharpFunc`2[T1,T2]) @@ -2110,15 +1724,20 @@ Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+Checked Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+NonStructuralComparison Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+OperatorIntrinsics Microsoft.FSharp.Core.Operators: Microsoft.FSharp.Core.Operators+Unchecked +Microsoft.FSharp.Core.Operators: SByte ToSByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], T) Microsoft.FSharp.Core.Operators: SByte ToSByte[T](T) Microsoft.FSharp.Core.Operators: Single InfinitySingle Microsoft.FSharp.Core.Operators: Single NaNSingle +Microsoft.FSharp.Core.Operators: Single ToSingle$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Single], T) Microsoft.FSharp.Core.Operators: Single ToSingle[T](T) Microsoft.FSharp.Core.Operators: Single get_InfinitySingle() Microsoft.FSharp.Core.Operators: Single get_NaNSingle() Microsoft.FSharp.Core.Operators: System.Collections.Generic.IEnumerable`1[T] CreateSequence[T](System.Collections.Generic.IEnumerable`1[T]) +Microsoft.FSharp.Core.Operators: System.Collections.Generic.IEnumerable`1[T] op_Range$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) +Microsoft.FSharp.Core.Operators: System.Collections.Generic.IEnumerable`1[T] op_RangeStep$W[T,TStep](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TStep], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TStep,T]], T, TStep, T) Microsoft.FSharp.Core.Operators: System.Collections.Generic.IEnumerable`1[T] op_RangeStep[T,TStep](T, TStep, T) Microsoft.FSharp.Core.Operators: System.Collections.Generic.IEnumerable`1[T] op_Range[T](T, T) +Microsoft.FSharp.Core.Operators: System.Decimal ToDecimal$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Decimal], T) Microsoft.FSharp.Core.Operators: System.Decimal ToDecimal[T](T) Microsoft.FSharp.Core.Operators: System.Exception Failure(System.String) Microsoft.FSharp.Core.Operators: System.IO.TextReader ConsoleIn[T]() @@ -2131,57 +1750,91 @@ Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, Sys Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue]) Microsoft.FSharp.Core.Operators: System.Type TypeDefOf[T]() Microsoft.FSharp.Core.Operators: System.Type TypeOf[T]() +Microsoft.FSharp.Core.Operators: T Abs$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Abs[T](T) +Microsoft.FSharp.Core.Operators: T Acos$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Acos[T](T) +Microsoft.FSharp.Core.Operators: T Asin$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Asin[T](T) +Microsoft.FSharp.Core.Operators: T Atan$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Atan[T](T) +Microsoft.FSharp.Core.Operators: T Ceiling$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Ceiling[T](T) +Microsoft.FSharp.Core.Operators: T Cos$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Cos[T](T) +Microsoft.FSharp.Core.Operators: T Cosh$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Cosh[T](T) Microsoft.FSharp.Core.Operators: T DefaultArg[T](Microsoft.FSharp.Core.FSharpOption`1[T], T) Microsoft.FSharp.Core.Operators: T DefaultValueArg[T](Microsoft.FSharp.Core.FSharpValueOption`1[T], T) Microsoft.FSharp.Core.Operators: T Exit[T](Int32) +Microsoft.FSharp.Core.Operators: T Exp$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Exp[T](T) Microsoft.FSharp.Core.Operators: T FailWith[T](System.String) +Microsoft.FSharp.Core.Operators: T Floor$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Floor[T](T) Microsoft.FSharp.Core.Operators: T Identity[T](T) Microsoft.FSharp.Core.Operators: T InvalidArg[T](System.String, System.String) Microsoft.FSharp.Core.Operators: T InvalidOp[T](System.String) Microsoft.FSharp.Core.Operators: T Lock[TLock,T](TLock, Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T]) +Microsoft.FSharp.Core.Operators: T Log$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) +Microsoft.FSharp.Core.Operators: T Log10$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Log10[T](T) Microsoft.FSharp.Core.Operators: T Log[T](T) Microsoft.FSharp.Core.Operators: T Max[T](T, T) Microsoft.FSharp.Core.Operators: T Min[T](T, T) Microsoft.FSharp.Core.Operators: T NullArg[T](System.String) +Microsoft.FSharp.Core.Operators: T PowInteger$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, Int32) Microsoft.FSharp.Core.Operators: T PowInteger[T](T, Int32) Microsoft.FSharp.Core.Operators: T Raise[T](System.Exception) Microsoft.FSharp.Core.Operators: T Reraise[T]() Microsoft.FSharp.Core.Operators: T Rethrow[T]() +Microsoft.FSharp.Core.Operators: T Round$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Round[T](T) +Microsoft.FSharp.Core.Operators: T Sin$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Sin[T](T) +Microsoft.FSharp.Core.Operators: T Sinh$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Sinh[T](T) +Microsoft.FSharp.Core.Operators: T Tan$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Tan[T](T) +Microsoft.FSharp.Core.Operators: T Tanh$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Tanh[T](T) +Microsoft.FSharp.Core.Operators: T Truncate$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T Truncate[T](T) Microsoft.FSharp.Core.Operators: T Unbox[T](System.Object) +Microsoft.FSharp.Core.Operators: T op_BitwiseAnd$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) Microsoft.FSharp.Core.Operators: T op_BitwiseAnd[T](T, T) +Microsoft.FSharp.Core.Operators: T op_BitwiseOr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) Microsoft.FSharp.Core.Operators: T op_BitwiseOr[T](T, T) Microsoft.FSharp.Core.Operators: T op_Dereference[T](Microsoft.FSharp.Core.FSharpRef`1[T]) +Microsoft.FSharp.Core.Operators: T op_ExclusiveOr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) Microsoft.FSharp.Core.Operators: T op_ExclusiveOr[T](T, T) +Microsoft.FSharp.Core.Operators: T op_Exponentiation$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,T]], T, TResult) Microsoft.FSharp.Core.Operators: T op_Exponentiation[T,TResult](T, TResult) +Microsoft.FSharp.Core.Operators: T op_LeftShift$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], T, Int32) Microsoft.FSharp.Core.Operators: T op_LeftShift[T](T, Int32) +Microsoft.FSharp.Core.Operators: T op_LogicalNot$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T op_LogicalNot[T](T) +Microsoft.FSharp.Core.Operators: T op_RightShift$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], T, Int32) Microsoft.FSharp.Core.Operators: T op_RightShift[T](T, Int32) +Microsoft.FSharp.Core.Operators: T op_UnaryNegation$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T op_UnaryNegation[T](T) +Microsoft.FSharp.Core.Operators: T op_UnaryPlus$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) Microsoft.FSharp.Core.Operators: T op_UnaryPlus[T](T) Microsoft.FSharp.Core.Operators: T1 Fst[T1,T2](System.Tuple`2[T1,T2]) +Microsoft.FSharp.Core.Operators: T2 Atan2$W[T1,T2](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T1,T2]], T1, T1) Microsoft.FSharp.Core.Operators: T2 Atan2[T1,T2](T1, T1) Microsoft.FSharp.Core.Operators: T2 Snd[T1,T2](System.Tuple`2[T1,T2]) +Microsoft.FSharp.Core.Operators: T3 op_Addition$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) Microsoft.FSharp.Core.Operators: T3 op_Addition[T1,T2,T3](T1, T2) +Microsoft.FSharp.Core.Operators: T3 op_Division$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) Microsoft.FSharp.Core.Operators: T3 op_Division[T1,T2,T3](T1, T2) +Microsoft.FSharp.Core.Operators: T3 op_Modulus$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) Microsoft.FSharp.Core.Operators: T3 op_Modulus[T1,T2,T3](T1, T2) +Microsoft.FSharp.Core.Operators: T3 op_Multiply$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) Microsoft.FSharp.Core.Operators: T3 op_Multiply[T1,T2,T3](T1, T2) +Microsoft.FSharp.Core.Operators: T3 op_Subtraction$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) Microsoft.FSharp.Core.Operators: T3 op_Subtraction[T1,T2,T3](T1, T2) +Microsoft.FSharp.Core.Operators: TResult Sqrt$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T) Microsoft.FSharp.Core.Operators: TResult Sqrt[T,TResult](T) Microsoft.FSharp.Core.Operators: TResult ToEnum[TResult](Int32) Microsoft.FSharp.Core.Operators: TResult Using[T,TResult](T, Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]) @@ -2191,9 +1844,15 @@ Microsoft.FSharp.Core.Operators: TResult op_PipeLeft[T,TResult](Microsoft.FSharp Microsoft.FSharp.Core.Operators: TResult op_PipeRight2[T1,T2,TResult](T1, T2, Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,TResult]]) Microsoft.FSharp.Core.Operators: TResult op_PipeRight3[T1,T2,T3,TResult](T1, T2, T3, Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,Microsoft.FSharp.Core.FSharpFunc`2[T3,TResult]]]) Microsoft.FSharp.Core.Operators: TResult op_PipeRight[T1,TResult](T1, Microsoft.FSharp.Core.FSharpFunc`2[T1,TResult]) +Microsoft.FSharp.Core.Operators: UInt16 ToUInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt16], T) Microsoft.FSharp.Core.Operators: UInt16 ToUInt16[T](T) +Microsoft.FSharp.Core.Operators: UInt32 ToUInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt32], T) +Microsoft.FSharp.Core.Operators: UInt32 ToUInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt32], T) Microsoft.FSharp.Core.Operators: UInt32 ToUInt32[T](T) +Microsoft.FSharp.Core.Operators: UInt32 ToUInt[T](T) +Microsoft.FSharp.Core.Operators: UInt64 ToUInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt64], T) Microsoft.FSharp.Core.Operators: UInt64 ToUInt64[T](T) +Microsoft.FSharp.Core.Operators: UIntPtr ToUIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UIntPtr], T) Microsoft.FSharp.Core.Operators: UIntPtr ToUIntPtr[T](T) Microsoft.FSharp.Core.Operators: Void Decrement(Microsoft.FSharp.Core.FSharpRef`1[System.Int32]) Microsoft.FSharp.Core.Operators: Void Ignore[T](T) @@ -2246,24 +1905,17 @@ Microsoft.FSharp.Core.OptionModule: TState Fold[T,TState](Microsoft.FSharp.Core. Microsoft.FSharp.Core.OptionModule: T[] ToArray[T](Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.OptionModule: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpOption`1[T]) Microsoft.FSharp.Core.OptionalArgumentAttribute: Void .ctor() +Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: System.Object[] Captures +Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: System.Object[] get_Captures() Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: System.String ToString() Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: System.String Value Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: System.String get_Value() -Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: Void .ctor(System.String) -Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: Void .ctor(System.String, System.Object[], System.Type[]) -Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: System.Object[] Captures -Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: System.Object[] get_Captures() Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: System.Type[] CaptureTypes Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: System.Type[] get_CaptureTypes() -Microsoft.FSharp.Core.PrintfFormat`5[TPrinter,TState,TResidue,TResult,TTuple]: System.String ToString() -Microsoft.FSharp.Core.PrintfFormat`5[TPrinter,TState,TResidue,TResult,TTuple]: System.String Value -Microsoft.FSharp.Core.PrintfFormat`5[TPrinter,TState,TResidue,TResult,TTuple]: System.String get_Value() +Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: Void .ctor(System.String) +Microsoft.FSharp.Core.PrintfFormat`4[TPrinter,TState,TResidue,TResult]: Void .ctor(System.String, System.Object[], System.Type[]) Microsoft.FSharp.Core.PrintfFormat`5[TPrinter,TState,TResidue,TResult,TTuple]: Void .ctor(System.String) Microsoft.FSharp.Core.PrintfFormat`5[TPrinter,TState,TResidue,TResult,TTuple]: Void .ctor(System.String, System.Object[], System.Type[]) -Microsoft.FSharp.Core.PrintfFormat`5[TPrinter,TState,TResidue,TResult,TTuple]: System.Object[] Captures -Microsoft.FSharp.Core.PrintfFormat`5[TPrinter,TState,TResidue,TResult,TTuple]: System.Object[] get_Captures() -Microsoft.FSharp.Core.PrintfFormat`5[TPrinter,TState,TResidue,TResult,TTuple]: System.Type[] CaptureTypes -Microsoft.FSharp.Core.PrintfFormat`5[TPrinter,TState,TResidue,TResult,TTuple]: System.Type[] get_CaptureTypes() Microsoft.FSharp.Core.PrintfModule: T PrintFormatLineToError[T](Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit]) Microsoft.FSharp.Core.PrintfModule: T PrintFormatLineToTextWriter[T](System.IO.TextWriter, Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit]) Microsoft.FSharp.Core.PrintfModule: T PrintFormatLine[T](Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit]) @@ -2353,25 +2005,45 @@ Microsoft.FSharp.Core.ValueOption: TState Fold[T,TState](Microsoft.FSharp.Core.F Microsoft.FSharp.Core.ValueOption: T[] ToArray[T](Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.ValueOption: Void Iterate[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.Unit], Microsoft.FSharp.Core.FSharpValueOption`1[T]) Microsoft.FSharp.Core.VolatileFieldAttribute: Void .ctor() +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Byte] ToByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Byte] ToByte[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Byte] ToUInt8$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Byte] ToUInt8[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Char] ToChar$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Char], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Char] ToChar[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Decimal] ToDecimal$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Decimal], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Decimal] ToDecimal[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Double] ToDouble$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Double], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Double] ToDouble[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Double] ToFloat$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Double], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Double] ToFloat[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int16] ToInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int16], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int16] ToInt16[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int32] ToInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int32] ToInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int32] ToInt32[T](System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int32] ToInt[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int64] ToInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int64], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int64] ToInt64[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.IntPtr] ToIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.IntPtr], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.IntPtr] ToIntPtr[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.SByte] ToInt8$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.SByte] ToInt8[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.SByte] ToSByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.SByte] ToSByte[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Single] ToFloat32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Single], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Single] ToFloat32[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Single] ToSingle$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Single], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Single] ToSingle[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt16] ToUInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt16], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt16] ToUInt16[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt32] ToUInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt32], System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt32] ToUInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt32], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt32] ToUInt32[T](System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt32] ToUInt[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt64] ToUInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt64], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt64] ToUInt64[T](System.Nullable`1[T]) +Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UIntPtr] ToUIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UIntPtr], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UIntPtr] ToUIntPtr[T](System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[TResult] ToEnum[TResult](System.Nullable`1[System.Int32]) Microsoft.FSharp.Linq.NullableOperators: Boolean op_EqualsQmark[T](T, System.Nullable`1[T]) @@ -2392,19 +2064,34 @@ Microsoft.FSharp.Linq.NullableOperators: Boolean op_QmarkLessGreaterQmark[T](Sys Microsoft.FSharp.Linq.NullableOperators: Boolean op_QmarkLessGreater[T](System.Nullable`1[T], T) Microsoft.FSharp.Linq.NullableOperators: Boolean op_QmarkLessQmark[T](System.Nullable`1[T], System.Nullable`1[T]) Microsoft.FSharp.Linq.NullableOperators: Boolean op_QmarkLess[T](System.Nullable`1[T], T) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_DivideQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_DivideQmark[T1,T2,T3](T1, System.Nullable`1[T2]) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_MinusQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_MinusQmark[T1,T2,T3](T1, System.Nullable`1[T2]) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_MultiplyQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_MultiplyQmark[T1,T2,T3](T1, System.Nullable`1[T2]) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_PercentQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_PercentQmark[T1,T2,T3](T1, System.Nullable`1[T2]) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_PlusQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_PlusQmark[T1,T2,T3](T1, System.Nullable`1[T2]) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkDivide$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], T2) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkDivideQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkDivideQmark[T1,T2,T3](System.Nullable`1[T1], System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkDivide[T1,T2,T3](System.Nullable`1[T1], T2) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMinus$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], T2) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMinusQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMinusQmark[T1,T2,T3](System.Nullable`1[T1], System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMinus[T1,T2,T3](System.Nullable`1[T1], T2) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMultiply$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], T2) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMultiplyQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMultiplyQmark[T1,T2,T3](System.Nullable`1[T1], System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMultiply[T1,T2,T3](System.Nullable`1[T1], T2) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPercent$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], T2) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPercentQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPercentQmark[T1,T2,T3](System.Nullable`1[T1], System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPercent[T1,T2,T3](System.Nullable`1[T1], T2) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPlus$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], T2) +Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPlusQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPlusQmark[T1,T2,T3](System.Nullable`1[T1], System.Nullable`1[T2]) Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPlus[T1,T2,T3](System.Nullable`1[T1], T2) Microsoft.FSharp.Linq.QueryBuilder: Boolean All[T,Q](Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]) @@ -2439,9 +2126,11 @@ Microsoft.FSharp.Linq.QueryBuilder: Microsoft.FSharp.Linq.QuerySource`2[TResult, Microsoft.FSharp.Linq.QueryBuilder: Microsoft.FSharp.Linq.QuerySource`2[TResult,Q] Select[T,Q,TResult](Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult]) Microsoft.FSharp.Linq.QueryBuilder: Microsoft.FSharp.Quotations.FSharpExpr`1[T] Quote[T](Microsoft.FSharp.Quotations.FSharpExpr`1[T]) Microsoft.FSharp.Linq.QueryBuilder: System.Linq.IQueryable`1[T] Run[T](Microsoft.FSharp.Quotations.FSharpExpr`1[Microsoft.FSharp.Linq.QuerySource`2[T,System.Linq.IQueryable]]) +Microsoft.FSharp.Linq.QueryBuilder: System.Nullable`1[TValue] AverageByNullable$W[T,Q,TValue](Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TValue]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TValue], Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[TValue,TValue]], Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,System.Nullable`1[TValue]]) Microsoft.FSharp.Linq.QueryBuilder: System.Nullable`1[TValue] AverageByNullable[T,Q,TValue](Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,System.Nullable`1[TValue]]) Microsoft.FSharp.Linq.QueryBuilder: System.Nullable`1[TValue] MaxByNullable[T,Q,TValue](Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,System.Nullable`1[TValue]]) Microsoft.FSharp.Linq.QueryBuilder: System.Nullable`1[TValue] MinByNullable[T,Q,TValue](Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,System.Nullable`1[TValue]]) +Microsoft.FSharp.Linq.QueryBuilder: System.Nullable`1[TValue] SumByNullable$W[T,Q,TValue](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TValue], Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[TValue,TValue]], Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,System.Nullable`1[TValue]]) Microsoft.FSharp.Linq.QueryBuilder: System.Nullable`1[TValue] SumByNullable[T,Q,TValue](Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,System.Nullable`1[TValue]]) Microsoft.FSharp.Linq.QueryBuilder: T ExactlyOneOrDefault[T,Q](Microsoft.FSharp.Linq.QuerySource`2[T,Q]) Microsoft.FSharp.Linq.QueryBuilder: T ExactlyOne[T,Q](Microsoft.FSharp.Linq.QuerySource`2[T,Q]) @@ -2451,9 +2140,11 @@ Microsoft.FSharp.Linq.QueryBuilder: T Head[T,Q](Microsoft.FSharp.Linq.QuerySourc Microsoft.FSharp.Linq.QueryBuilder: T LastOrDefault[T,Q](Microsoft.FSharp.Linq.QuerySource`2[T,Q]) Microsoft.FSharp.Linq.QueryBuilder: T Last[T,Q](Microsoft.FSharp.Linq.QuerySource`2[T,Q]) Microsoft.FSharp.Linq.QueryBuilder: T Nth[T,Q](Microsoft.FSharp.Linq.QuerySource`2[T,Q], Int32) +Microsoft.FSharp.Linq.QueryBuilder: TValue AverageBy$W[T,Q,TValue](Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TValue]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TValue], Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[TValue,TValue]], Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,TValue]) Microsoft.FSharp.Linq.QueryBuilder: TValue AverageBy[T,Q,TValue](Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,TValue]) Microsoft.FSharp.Linq.QueryBuilder: TValue MaxBy[T,Q,TValue](Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,TValue]) Microsoft.FSharp.Linq.QueryBuilder: TValue MinBy[T,Q,TValue](Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,TValue]) +Microsoft.FSharp.Linq.QueryBuilder: TValue SumBy$W[T,Q,TValue](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TValue], Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[TValue,TValue]], Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,TValue]) Microsoft.FSharp.Linq.QueryBuilder: TValue SumBy[T,Q,TValue](Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,TValue]) Microsoft.FSharp.Linq.QueryBuilder: Void .ctor() Microsoft.FSharp.Linq.QueryRunExtensions.HighPriority: System.Collections.Generic.IEnumerable`1[T] RunQueryAsEnumerable[T](Microsoft.FSharp.Linq.QueryBuilder, Microsoft.FSharp.Quotations.FSharpExpr`1[Microsoft.FSharp.Linq.QuerySource`2[T,System.Collections.IEnumerable]]) @@ -2605,6 +2296,8 @@ Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr A Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr Applications(Microsoft.FSharp.Quotations.FSharpExpr, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]]) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr Call(Microsoft.FSharp.Quotations.FSharpExpr, System.Reflection.MethodInfo, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr Call(System.Reflection.MethodInfo, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) +Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr CallWithWitnesses(Microsoft.FSharp.Quotations.FSharpExpr, System.Reflection.MethodInfo, System.Reflection.MethodInfo, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr], Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) +Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr CallWithWitnesses(System.Reflection.MethodInfo, System.Reflection.MethodInfo, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr], Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr Coerce(Microsoft.FSharp.Quotations.FSharpExpr, System.Type) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr DefaultValue(System.Type) Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr Deserialize(System.Type, Microsoft.FSharp.Collections.FSharpList`1[System.Type], Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr], Byte[]) @@ -2657,18 +2350,8 @@ Microsoft.FSharp.Quotations.FSharpExpr: System.Type Type Microsoft.FSharp.Quotations.FSharpExpr: System.Type get_Type() Microsoft.FSharp.Quotations.FSharpExpr: Void RegisterReflectedDefinitions(System.Reflection.Assembly, System.String, Byte[]) Microsoft.FSharp.Quotations.FSharpExpr: Void RegisterReflectedDefinitions(System.Reflection.Assembly, System.String, Byte[], System.Type[]) -Microsoft.FSharp.Quotations.FSharpExpr`1[T]: Boolean Equals(System.Object) -Microsoft.FSharp.Quotations.FSharpExpr`1[T]: Int32 GetHashCode() -Microsoft.FSharp.Quotations.FSharpExpr`1[T]: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr] CustomAttributes -Microsoft.FSharp.Quotations.FSharpExpr`1[T]: Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr] get_CustomAttributes() Microsoft.FSharp.Quotations.FSharpExpr`1[T]: Microsoft.FSharp.Quotations.FSharpExpr Raw -Microsoft.FSharp.Quotations.FSharpExpr`1[T]: Microsoft.FSharp.Quotations.FSharpExpr Substitute(Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Quotations.FSharpVar,Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Quotations.FSharpExpr]]) Microsoft.FSharp.Quotations.FSharpExpr`1[T]: Microsoft.FSharp.Quotations.FSharpExpr get_Raw() -Microsoft.FSharp.Quotations.FSharpExpr`1[T]: System.Collections.Generic.IEnumerable`1[Microsoft.FSharp.Quotations.FSharpVar] GetFreeVars() -Microsoft.FSharp.Quotations.FSharpExpr`1[T]: System.String ToString() -Microsoft.FSharp.Quotations.FSharpExpr`1[T]: System.String ToString(Boolean) -Microsoft.FSharp.Quotations.FSharpExpr`1[T]: System.Type Type -Microsoft.FSharp.Quotations.FSharpExpr`1[T]: System.Type get_Type() Microsoft.FSharp.Quotations.FSharpVar: Boolean Equals(System.Object) Microsoft.FSharp.Quotations.FSharpVar: Boolean IsMutable Microsoft.FSharp.Quotations.FSharpVar: Boolean get_IsMutable() @@ -2715,6 +2398,7 @@ Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1 Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`3[System.Type,Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpVar],Microsoft.FSharp.Quotations.FSharpExpr]] NewDelegatePattern(Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`4[Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Quotations.FSharpExpr],System.Reflection.PropertyInfo,Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr],Microsoft.FSharp.Quotations.FSharpExpr]] PropertySetPattern(Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`4[Microsoft.FSharp.Quotations.FSharpVar,Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Quotations.FSharpExpr]] ForIntegerRangeLoopPattern(Microsoft.FSharp.Quotations.FSharpExpr) +Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`5[Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Quotations.FSharpExpr],System.Reflection.MethodInfo,System.Reflection.MethodInfo,Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr],Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]]] CallWithWitnessesPattern(Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`5[Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Quotations.FSharpVar,Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Quotations.FSharpVar,Microsoft.FSharp.Quotations.FSharpExpr]] TryWithPattern(Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[System.Type] DefaultValuePattern(Microsoft.FSharp.Quotations.FSharpExpr) Microsoft.FSharp.Reflection.FSharpReflectionExtensions: Boolean FSharpType.IsExceptionRepresentation.Static(System.Type, Microsoft.FSharp.Core.FSharpOption`1[System.Boolean]) @@ -2787,169 +2471,14 @@ Microsoft.FSharp.Reflection.UnionCaseInfo: System.String ToString() Microsoft.FSharp.Reflection.UnionCaseInfo: System.String get_Name() Microsoft.FSharp.Reflection.UnionCaseInfo: System.Type DeclaringType Microsoft.FSharp.Reflection.UnionCaseInfo: System.Type get_DeclaringType() -Microsoft.FSharp.Collections.ArrayModule: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) -Microsoft.FSharp.Collections.ArrayModule: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T[]) -Microsoft.FSharp.Collections.ArrayModule: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) -Microsoft.FSharp.Collections.ArrayModule: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T[]) -Microsoft.FSharp.Collections.ComparisonIdentity: System.Collections.Generic.IComparer`1[T] NonStructural$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]]) -Microsoft.FSharp.Collections.HashIdentity: System.Collections.Generic.IEqualityComparer`1[T] NonStructural$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]]) -Microsoft.FSharp.Collections.ListModule: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.FSharpList`1[T]) -Microsoft.FSharp.Collections.ListModule: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Collections.FSharpList`1[T]) -Microsoft.FSharp.Collections.ListModule: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.FSharpList`1[T]) -Microsoft.FSharp.Collections.ListModule: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], Microsoft.FSharp.Collections.FSharpList`1[T]) -Microsoft.FSharp.Collections.SeqModule: T Average$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], System.Collections.Generic.IEnumerable`1[T]) -Microsoft.FSharp.Collections.SeqModule: T Sum$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], System.Collections.Generic.IEnumerable`1[T]) -Microsoft.FSharp.Collections.SeqModule: TResult AverageBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], System.Collections.Generic.IEnumerable`1[T]) -Microsoft.FSharp.Collections.SeqModule: TResult SumBy$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TResult], Microsoft.FSharp.Core.FSharpFunc`2[TResult,Microsoft.FSharp.Core.FSharpFunc`2[TResult,TResult]], Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], System.Collections.Generic.IEnumerable`1[T]) -Microsoft.FSharp.Core.ExtraTopLevelOperators+Checked: Byte ToByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], T) -Microsoft.FSharp.Core.ExtraTopLevelOperators+Checked: SByte ToSByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], T) -Microsoft.FSharp.Core.ExtraTopLevelOperators: Byte ToByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], T) -Microsoft.FSharp.Core.ExtraTopLevelOperators: Double ToDouble$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Double], T) -Microsoft.FSharp.Core.ExtraTopLevelOperators: SByte ToSByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], T) -Microsoft.FSharp.Core.ExtraTopLevelOperators: Single ToSingle$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Single], T) -Microsoft.FSharp.Core.LanguagePrimitives: T DivideByInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], T, Int32) -Microsoft.FSharp.Core.LanguagePrimitives: T GenericOne$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T]) -Microsoft.FSharp.Core.LanguagePrimitives: T GenericZero$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T]) -Microsoft.FSharp.Core.LanguagePrimitives: TResult CheckedSubtractionDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult CheckedUnaryNegationDynamic[T,TResult](T) -Microsoft.FSharp.Core.LanguagePrimitives: TResult DivisionDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult ModulusDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult BitwiseAndDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult ExclusiveOrDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult BitwiseOrDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult EqualityDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult ExplicitDynamic[T,TResult](T) -Microsoft.FSharp.Core.LanguagePrimitives: TResult GreaterThanDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult GreaterThanOrEqualDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult InequalityDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult LeftShiftDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult LessThanDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult LessThanOrEqualDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult LogicalNotDynamic[T,TResult](T) -Microsoft.FSharp.Core.LanguagePrimitives: TResult RightShiftDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult SubtractionDynamic[T1,T2,TResult](T1, T2) -Microsoft.FSharp.Core.LanguagePrimitives: TResult UnaryNegationDynamic[T,TResult](T) -Microsoft.FSharp.Core.Operators+Checked: Byte ToByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], T) -Microsoft.FSharp.Core.Operators+Checked: Char ToChar$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Char], T) -Microsoft.FSharp.Core.Operators+Checked: Int16 ToInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int16], T) -Microsoft.FSharp.Core.Operators+Checked: Int32 ToInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], T) -Microsoft.FSharp.Core.Operators+Checked: Int32 ToInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], T) -Microsoft.FSharp.Core.Operators+Checked: Int64 ToInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int64], T) -Microsoft.FSharp.Core.Operators+Checked: IntPtr ToIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.IntPtr], T) -Microsoft.FSharp.Core.Operators+Checked: SByte ToSByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], T) -Microsoft.FSharp.Core.Operators+Checked: T op_UnaryNegation$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators+Checked: T3 op_Addition$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) -Microsoft.FSharp.Core.Operators+Checked: T3 op_Multiply$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) -Microsoft.FSharp.Core.Operators+Checked: T3 op_Subtraction$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) -Microsoft.FSharp.Core.Operators+Checked: UInt16 ToUInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt16], T) -Microsoft.FSharp.Core.Operators+Checked: UInt32 ToUInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt32], T) -Microsoft.FSharp.Core.Operators+Checked: UInt64 ToUInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt64], T) -Microsoft.FSharp.Core.Operators+Checked: UIntPtr ToUIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UIntPtr], T) -Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_Equality$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], T, T) -Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_GreaterThanOrEqual$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], T, TResult) -Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_GreaterThan$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], T, TResult) -Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_Inequality$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], T, T) -Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_LessThanOrEqual$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], T, TResult) -Microsoft.FSharp.Core.Operators+NonStructuralComparison: Boolean op_LessThan$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,System.Boolean]], T, TResult) -Microsoft.FSharp.Core.Operators+NonStructuralComparison: Int32 Compare$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], T, T) -Microsoft.FSharp.Core.Operators+NonStructuralComparison: T Max$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], T, T) -Microsoft.FSharp.Core.Operators+NonStructuralComparison: T Min$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,System.Boolean]], T, T) -Microsoft.FSharp.Core.Operators: Byte ToByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], T) -Microsoft.FSharp.Core.Operators: Char ToChar$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Char], T) -Microsoft.FSharp.Core.Operators: Double ToDouble$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Double], T) -Microsoft.FSharp.Core.Operators: Int16 ToInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int16], T) -Microsoft.FSharp.Core.Operators: Int32 Sign$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], T) -Microsoft.FSharp.Core.Operators: Int32 ToInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], T) -Microsoft.FSharp.Core.Operators: Int32 ToInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], T) -Microsoft.FSharp.Core.Operators: Int64 ToInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int64], T) -Microsoft.FSharp.Core.Operators: IntPtr ToIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.IntPtr], T) -Microsoft.FSharp.Core.Operators: SByte ToSByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], T) -Microsoft.FSharp.Core.Operators: Single ToSingle$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Single], T) -Microsoft.FSharp.Core.Operators: System.Collections.Generic.IEnumerable`1[T] op_RangeStep$W[T,TStep](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TStep], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TStep,T]], T, TStep, T) -Microsoft.FSharp.Core.Operators: System.Collections.Generic.IEnumerable`1[T] op_Range$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) -Microsoft.FSharp.Core.Operators: System.Decimal ToDecimal$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Decimal], T) -Microsoft.FSharp.Core.Operators: T Abs$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Acos$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Asin$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Atan$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Ceiling$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Cos$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Cosh$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Exp$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Floor$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Log10$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Log$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T PowInteger$W[T](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,T], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, Int32) -Microsoft.FSharp.Core.Operators: T Round$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Sin$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Sinh$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Tan$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Tanh$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T Truncate$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T op_BitwiseAnd$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) -Microsoft.FSharp.Core.Operators: T op_BitwiseOr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) -Microsoft.FSharp.Core.Operators: T op_ExclusiveOr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[T,T]], T, T) -Microsoft.FSharp.Core.Operators: T op_Exponentiation$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[TResult,T]], T, TResult) -Microsoft.FSharp.Core.Operators: T op_LeftShift$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], T, Int32) -Microsoft.FSharp.Core.Operators: T op_LogicalNot$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T op_RightShift$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,T]], T, Int32) -Microsoft.FSharp.Core.Operators: T op_UnaryNegation$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T op_UnaryPlus$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,T], T) -Microsoft.FSharp.Core.Operators: T2 Atan2$W[T1,T2](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T1,T2]], T1, T1) -Microsoft.FSharp.Core.Operators: T3 op_Addition$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) -Microsoft.FSharp.Core.Operators: T3 op_Division$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) -Microsoft.FSharp.Core.Operators: T3 op_Modulus$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) -Microsoft.FSharp.Core.Operators: T3 op_Multiply$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) -Microsoft.FSharp.Core.Operators: T3 op_Subtraction$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, T2) -Microsoft.FSharp.Core.Operators: TResult Sqrt$W[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult], T) -Microsoft.FSharp.Core.Operators: UInt32 ToUInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt32], T) -Microsoft.FSharp.Core.Operators: UInt16 ToUInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt16], T) -Microsoft.FSharp.Core.Operators: UInt32 ToUInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt32], T) -Microsoft.FSharp.Core.Operators: UInt64 ToUInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt64], T) -Microsoft.FSharp.Core.Operators: UIntPtr ToUIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UIntPtr], T) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Byte] ToByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Byte] ToUInt8$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Byte], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Char] ToChar$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Char], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Decimal] ToDecimal$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Decimal], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Double] ToDouble$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Double], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Double] ToFloat$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Double], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int16] ToInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int16], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int32] ToInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int32] ToInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int32], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Int64] ToInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Int64], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.IntPtr] ToIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.IntPtr], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.SByte] ToInt8$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.SByte] ToSByte$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.SByte], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Single] ToFloat32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Single], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.Single] ToSingle$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.Single], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt16] ToUInt16$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt16], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt32] ToUInt32$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt32], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt32] ToUInt$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt32], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UInt64] ToUInt64$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UInt64], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableModule: System.Nullable`1[System.UIntPtr] ToUIntPtr$W[T](Microsoft.FSharp.Core.FSharpFunc`2[T,System.UIntPtr], System.Nullable`1[T]) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_DivideQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, System.Nullable`1[T2]) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_MinusQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, System.Nullable`1[T2]) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_MultiplyQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, System.Nullable`1[T2]) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_PercentQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, System.Nullable`1[T2]) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_PlusQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], T1, System.Nullable`1[T2]) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkDivideQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], System.Nullable`1[T2]) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkDivide$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], T2) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMinusQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], System.Nullable`1[T2]) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMinus$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], T2) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMultiplyQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], System.Nullable`1[T2]) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkMultiply$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], T2) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPercentQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], System.Nullable`1[T2]) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPercent$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], T2) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPlusQmark$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], System.Nullable`1[T2]) -Microsoft.FSharp.Linq.NullableOperators: System.Nullable`1[T3] op_QmarkPlus$W[T1,T2,T3](Microsoft.FSharp.Core.FSharpFunc`2[T1,Microsoft.FSharp.Core.FSharpFunc`2[T2,T3]], System.Nullable`1[T1], T2) -Microsoft.FSharp.Linq.QueryBuilder: System.Nullable`1[TValue] AverageByNullable$W[T,Q,TValue](Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TValue]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TValue], Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[TValue,TValue]], Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,System.Nullable`1[TValue]]) -Microsoft.FSharp.Linq.QueryBuilder: System.Nullable`1[TValue] SumByNullable$W[T,Q,TValue](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TValue], Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[TValue,TValue]], Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,System.Nullable`1[TValue]]) -Microsoft.FSharp.Linq.QueryBuilder: TValue AverageBy$W[T,Q,TValue](Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,TValue]], Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TValue], Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[TValue,TValue]], Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,TValue]) -Microsoft.FSharp.Linq.QueryBuilder: TValue SumBy$W[T,Q,TValue](Microsoft.FSharp.Core.FSharpFunc`2[Microsoft.FSharp.Core.Unit,TValue], Microsoft.FSharp.Core.FSharpFunc`2[TValue,Microsoft.FSharp.Core.FSharpFunc`2[TValue,TValue]], Microsoft.FSharp.Linq.QuerySource`2[T,Q], Microsoft.FSharp.Core.FSharpFunc`2[T,TValue]) -Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr CallWithWitnesses(Microsoft.FSharp.Quotations.FSharpExpr, System.Reflection.MethodInfo, System.Reflection.MethodInfo, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr], Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) -Microsoft.FSharp.Quotations.FSharpExpr: Microsoft.FSharp.Quotations.FSharpExpr CallWithWitnesses(System.Reflection.MethodInfo, System.Reflection.MethodInfo, Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr], Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]) -Microsoft.FSharp.Quotations.PatternsModule: Microsoft.FSharp.Core.FSharpOption`1[System.Tuple`5[Microsoft.FSharp.Core.FSharpOption`1[Microsoft.FSharp.Quotations.FSharpExpr],System.Reflection.MethodInfo,System.Reflection.MethodInfo,Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr],Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr]]] CallWithWitnessesPattern(Microsoft.FSharp.Quotations.FSharpExpr) " +#if NETCOREAPP +// This is in netstandard 2.1 + let expected = + expected + + """Microsoft.FSharp.Control.TaskBuilderBase: Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T] Using[TResource,TOverall,T](TResource, Microsoft.FSharp.Core.FSharpFunc`2[TResource,Microsoft.FSharp.Core.CompilerServices.ResumableCode`2[Microsoft.FSharp.Control.TaskStateMachineData`1[TOverall],T]]) +""" +#endif #if DEBUG let expected = expected + diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index a3331b19aaf..6f8a8210acf 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -21,14 +21,11 @@ open TestFramework [] type ILVerifier (dllFilePath: string) = - member this.VerifyIL (qualifiedItemName: string, expectedIL: string) = - ILChecker.checkILItem qualifiedItemName dllFilePath [ expectedIL ] - member this.VerifyIL (expectedIL: string list) = ILChecker.checkIL dllFilePath expectedIL - member this.VerifyILWithLineNumbers (qualifiedItemName: string, expectedIL: string) = - ILChecker.checkILItemWithLineNumbers qualifiedItemName dllFilePath [ expectedIL ] + //member this.VerifyILWithDebugPoints (expectedIL: string list) = + // ILChecker.checkILWithDebugPoints dllFilePath expectedIL type Worker () = inherit MarshalByRefObject() @@ -129,9 +126,14 @@ type CompilerAssert private () = static let rawCompile inputFilePath outputFilePath isExe options source = File.WriteAllText (inputFilePath, source) let args = - options - |> Array.append defaultProjectOptions.OtherOptions - |> Array.append [| "fsc.dll"; inputFilePath; "-o:" + outputFilePath; (if isExe then "--target:exe" else "--target:library"); "--nowin32manifest" |] + [| yield "fsc.dll"; + yield inputFilePath; + yield "-o:" + outputFilePath; + yield (if isExe then "--target:exe" else "--target:library"); + yield "--nowin32manifest" + yield! defaultProjectOptions.OtherOptions + yield! options + |] let errors, _ = checker.Compile args |> Async.RunImmediate errors, outputFilePath diff --git a/tests/FSharp.Test.Utilities/ILChecker.fs b/tests/FSharp.Test.Utilities/ILChecker.fs index c7a65f00ac9..6357af6102d 100644 --- a/tests/FSharp.Test.Utilities/ILChecker.fs +++ b/tests/FSharp.Test.Utilities/ILChecker.fs @@ -28,7 +28,7 @@ module ILChecker = (fun me -> String.Empty) ) - let private checkILAux' ildasmArgs dllFilePath expectedIL = + let private checkILPrim ildasmArgs dllFilePath expectedIL = let ilFilePath = Path.ChangeExtension(dllFilePath, ".il") let mutable errorMsgOpt = None @@ -36,7 +36,9 @@ module ILChecker = try let ildasmPath = config.ILDASM - let stdErr, exitCode = exec ildasmPath (ildasmArgs @ [ sprintf "%s -out=%s" dllFilePath ilFilePath ]) + let ildasmFullArgs = [ yield dllFilePath; yield sprintf "-out=%s" ilFilePath; yield! ildasmArgs ] + + let stdErr, exitCode = exec ildasmPath ildasmFullArgs if exitCode <> 0 then failwith (sprintf "ILASM Expected exit code \"0\", got \"%d\"\nSTDERR: %s" exitCode stdErr) @@ -46,20 +48,22 @@ module ILChecker = let unifyRuntimeAssemblyName ilCode = System.Text.RegularExpressions.Regex.Replace(ilCode, - "\[System.Runtime\]|\[System.Runtime.Extensions\]|\[mscorlib\]","[runtime]", + "\[System.Runtime\]|\[System.Console\]|\[System.Runtime.Extensions\]|\[mscorlib\]","[runtime]", System.Text.RegularExpressions.RegexOptions.Singleline) - let text = - let raw = File.ReadAllText(ilFilePath) + let raw = File.ReadAllText(ilFilePath) + + let textAfterUnifyingAssemblies = let asmName = Path.GetFileNameWithoutExtension(dllFilePath) raw.Replace(asmName, "assembly") |> unifyRuntimeAssemblyName + let blockComments = @"/\*(.*?)\*/" let lineComments = @"//(.*?)\r?\n" let strings = @"""((\\[^\n]|[^""\n])*)""" let verbatimStrings = @"@(""[^""]*"")+" let textNoComments = - System.Text.RegularExpressions.Regex.Replace(text, + System.Text.RegularExpressions.Regex.Replace(textAfterUnifyingAssemblies, blockComments + "|" + lineComments + "|" + strings + "|" + verbatimStrings, (fun me -> if (me.Value.StartsWith("/*") || me.Value.StartsWith("//")) then @@ -109,23 +113,25 @@ module ILChecker = | _ -> (true, String.Empty, String.Empty) let private checkILAux ildasmArgs dllFilePath expectedIL = - let (success, errorMsg, _) = checkILAux' ildasmArgs dllFilePath expectedIL + let (success, errorMsg, _) = checkILPrim ildasmArgs dllFilePath expectedIL if not success then Assert.Fail(errorMsg) else () - let checkILItem item dllFilePath expectedIL = - checkILAux [ sprintf "/item:%s" item ] dllFilePath expectedIL - - let checkILItemWithLineNumbers item dllFilePath expectedIL = - checkILAux [ sprintf "/item:\"%s\"" item; "/linenum" ] dllFilePath expectedIL + // This doesn't work because the '/linenum' is being ignored by + // the version of ILDASM we are using, which we acquire from a nuget package + //let checkILWithDebugPoints dllFilePath expectedIL = + // checkILAux [ "/linenum" ] dllFilePath expectedIL let checkIL dllFilePath expectedIL = checkILAux [] dllFilePath expectedIL let verifyIL (dllFilePath: string) (expectedIL: string) = checkIL dllFilePath [expectedIL] - let verifyILAndReturnActual (dllFilePath: string) (expectedIL: string) = checkILAux' [] dllFilePath [expectedIL] + + let verifyILAndReturnActual (dllFilePath: string) (expectedIL: string) = + checkILPrim [] dllFilePath [expectedIL] + let reassembleIL ilFilePath dllFilePath = let ilasmPath = config.ILASM let errors, _ = exec ilasmPath ([ sprintf "%s /output=%s /dll" ilFilePath dllFilePath ]) diff --git a/tests/benchmarks/TaskPerf/TaskBuilder.fs b/tests/benchmarks/TaskPerf/TaskBuilder.fs new file mode 100644 index 00000000000..9d3683e4b27 --- /dev/null +++ b/tests/benchmarks/TaskPerf/TaskBuilder.fs @@ -0,0 +1,416 @@ +// TaskBuilder.fs - TPL task computation expressions for F# +// +// Written in 2016 by Robert Peele (humbobst@gmail.com) +// New operator-based overload resolution for F# 4.0 compatibility by Gustavo Leon in 2018. +// +// To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights +// to this software to the public domain worldwide. This software is distributed without any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication along with this software. +// If not, see . + +namespace TaskBuilderTasks +open System +open System.Threading.Tasks +open System.Runtime.CompilerServices + +// This module is not really obsolete, but it's not intended to be referenced directly from user code. +// However, it can't be private because it is used within inline functions that *are* user-visible. +// Marking it as obsolete is a workaround to hide it from auto-completion tools. +[] +module TaskBuilder = + /// Represents the state of a computation: + /// either awaiting something with a continuation, + /// or completed with a return value. + type Step<'a> = + | Await of ICriticalNotifyCompletion * (unit -> Step<'a>) + | Return of 'a + /// We model tail calls explicitly, but still can't run them without O(n) memory usage. + | ReturnFrom of 'a Task + /// Implements the machinery of running a `Step<'m, 'm>` as a task returning a continuation task. + and StepStateMachine<'a>(firstStep) as this = + let methodBuilder = AsyncTaskMethodBuilder<'a Task>() + /// The continuation we left off awaiting on our last MoveNext(). + let mutable continuation = fun () -> firstStep + /// Returns next pending awaitable or null if exiting (including tail call). + let nextAwaitable() = + try + match continuation() with + | Return r -> + methodBuilder.SetResult(Task.FromResult(r)) + null + | ReturnFrom t -> + methodBuilder.SetResult(t) + null + | Await (await, next) -> + continuation <- next + await + with + | exn -> + methodBuilder.SetException(exn) + null + let mutable self = this + + /// Start execution as a `Task>`. + member __.Run() = + methodBuilder.Start(&self) + methodBuilder.Task + + interface IAsyncStateMachine with + /// Proceed to one of three states: result, failure, or awaiting. + /// If awaiting, MoveNext() will be called again when the awaitable completes. + member __.MoveNext() = + let mutable await = nextAwaitable() + if not (isNull await) then + // Tell the builder to call us again when this thing is done. + methodBuilder.AwaitUnsafeOnCompleted(&await, &self) + member __.SetStateMachine(_) = () // Doesn't really apply since we're a reference type. + + let unwrapException (agg : AggregateException) = + let inners = agg.InnerExceptions + if inners.Count = 1 then inners.[0] + else agg :> Exception + + /// Used to represent no-ops like the implicit empty "else" branch of an "if" expression. + let zero = Return () + + /// Used to return a value. + let ret (x : 'a) = Return x + + type Binder<'out> = + // We put the output generic parameter up here at the class level, so it doesn't get subject to + // inline rules. If we put it all in the inline function, then the compiler gets confused at the + // below and demands that the whole function either is limited to working with (x : obj), or must + // be inline itself. + // + // let yieldThenReturn (x : 'a) = + // task { + // do! Task.Yield() + // return x + // } + + static member inline GenericAwait< ^abl, ^awt, ^inp + when ^abl : (member GetAwaiter : unit -> ^awt) + and ^awt :> ICriticalNotifyCompletion + and ^awt : (member get_IsCompleted : unit -> bool) + and ^awt : (member GetResult : unit -> ^inp) > + (abl : ^abl, continuation : ^inp -> 'out Step) : 'out Step = + let awt = (^abl : (member GetAwaiter : unit -> ^awt)(abl)) // get an awaiter from the awaitable + if (^awt : (member get_IsCompleted : unit -> bool)(awt)) then // shortcut to continue immediately + continuation (^awt : (member GetResult : unit -> ^inp)(awt)) + else + Await (awt, fun () -> continuation (^awt : (member GetResult : unit -> ^inp)(awt))) + + static member inline GenericAwaitConfigureFalse< ^tsk, ^abl, ^awt, ^inp + when ^tsk : (member ConfigureAwait : bool -> ^abl) + and ^abl : (member GetAwaiter : unit -> ^awt) + and ^awt :> ICriticalNotifyCompletion + and ^awt : (member get_IsCompleted : unit -> bool) + and ^awt : (member GetResult : unit -> ^inp) > + (tsk : ^tsk, continuation : ^inp -> 'out Step) : 'out Step = + let abl = (^tsk : (member ConfigureAwait : bool -> ^abl)(tsk, false)) + Binder<'out>.GenericAwait(abl, continuation) + + /// Special case of the above for `Task<'a>`. Have to write this out by hand to avoid confusing the compiler + /// trying to decide between satisfying the constraints with `Task` or `Task<'a>`. + let bindTask (task : 'a Task) (continuation : 'a -> Step<'b>) = + let awt = task.GetAwaiter() + if awt.IsCompleted then // Proceed to the next step based on the result we already have. + continuation(awt.GetResult()) + else // Await and continue later when a result is available. + Await (awt, (fun () -> continuation(awt.GetResult()))) + + /// Special case of the above for `Task<'a>`, for the context-insensitive builder. + /// Have to write this out by hand to avoid confusing the compiler thinking our built-in bind method + /// defined on the builder has fancy generic constraints on inp and out parameters. + let bindTaskConfigureFalse (task : 'a Task) (continuation : 'a -> Step<'b>) = + let awt = task.ConfigureAwait(false).GetAwaiter() + if awt.IsCompleted then // Proceed to the next step based on the result we already have. + continuation(awt.GetResult()) + else // Await and continue later when a result is available. + Await (awt, (fun () -> continuation(awt.GetResult()))) + + /// Chains together a step with its following step. + /// Note that this requires that the first step has no result. + /// This prevents constructs like `task { return 1; return 2; }`. + let rec combine (step : Step) (continuation : unit -> Step<'b>) = + match step with + | Return _ -> continuation() + | ReturnFrom t -> + Await (t.GetAwaiter(), continuation) + | Await (awaitable, next) -> + Await (awaitable, fun () -> combine (next()) continuation) + + /// Builds a step that executes the body while the condition predicate is true. + let whileLoop (cond : unit -> bool) (body : unit -> Step) = + if cond() then + // Create a self-referencing closure to test whether to repeat the loop on future iterations. + let rec repeat () = + if cond() then + let body = body() + match body with + | Return _ -> repeat() + | ReturnFrom t -> Await(t.GetAwaiter(), repeat) + | Await (awaitable, next) -> + Await (awaitable, fun () -> combine (next()) repeat) + else zero + // Run the body the first time and chain it to the repeat logic. + combine (body()) repeat + else zero + + /// Wraps a step in a try/with. This catches exceptions both in the evaluation of the function + /// to retrieve the step, and in the continuation of the step (if any). + let rec tryWith(step : unit -> Step<'a>) (catch : exn -> Step<'a>) = + try + match step() with + | Return _ as i -> i + | ReturnFrom t -> + let awaitable = t.GetAwaiter() + Await(awaitable, fun () -> + try + awaitable.GetResult() |> Return + with + | exn -> catch exn) + | Await (awaitable, next) -> Await (awaitable, fun () -> tryWith next catch) + with + | exn -> catch exn + + /// Wraps a step in a try/finally. This catches exceptions both in the evaluation of the function + /// to retrieve the step, and in the continuation of the step (if any). + let rec tryFinally (step : unit -> Step<'a>) fin = + let step = + try step() + // Important point: we use a try/with, not a try/finally, to implement tryFinally. + // The reason for this is that if we're just building a continuation, we definitely *shouldn't* + // execute the `fin()` part yet -- the actual execution of the asynchronous code hasn't completed! + with + | _ -> + fin() + reraise() + match step with + | Return _ as i -> + fin() + i + | ReturnFrom t -> + let awaitable = t.GetAwaiter() + Await(awaitable, fun () -> + let result = + try + awaitable.GetResult() |> Return + with + | _ -> + fin() + reraise() + fin() // if we got here we haven't run fin(), because we would've reraised after doing so + result) + | Await (awaitable, next) -> + Await (awaitable, fun () -> tryFinally next fin) + + /// Implements a using statement that disposes `disp` after `body` has completed. + let using (disp : #IDisposable) (body : _ -> Step<'a>) = + // A using statement is just a try/finally with the finally block disposing if non-null. + tryFinally + (fun () -> body disp) + (fun () -> if not (isNull (box disp)) then disp.Dispose()) + + /// Implements a loop that runs `body` for each element in `sequence`. + let forLoop (sequence : 'a seq) (body : 'a -> Step) = + // A for loop is just a using statement on the sequence's enumerator... + using (sequence.GetEnumerator()) + // ... and its body is a while loop that advances the enumerator and runs the body on each element. + (fun e -> whileLoop e.MoveNext (fun () -> body e.Current)) + + /// Runs a step as a task -- with a short-circuit for immediately completed steps. + let run (firstStep : unit -> Step<'a>) = + try + match firstStep() with + | Return x -> Task.FromResult(x) + | ReturnFrom t -> t + | Await _ as step -> StepStateMachine<'a>(step).Run().Unwrap() // sadly can't do tail recursion + // Any exceptions should go on the task, rather than being thrown from this call. + // This matches C# behavior where you won't see an exception until awaiting the task, + // even if it failed before reaching the first "await". + with + | exn -> + let src = new TaskCompletionSource<_>() + src.SetException(exn) + src.Task + + // We have to have a dedicated overload for Task<'a> so the compiler doesn't get confused with Convenience overloads for Asyncs + // Everything else can use bindGenericAwaitable via an extension member + + type Priority3 = obj + type Priority2 = IComparable + + type BindS = Priority1 with + static member inline (>>=) (_:Priority2, taskLike : 't) = fun (k: _ -> 'b Step) -> Binder<'b>.GenericAwait (taskLike, k): 'b Step + static member (>>=) ( Priority1, task: 'a Task) = fun (k: 'a -> 'b Step) -> bindTask task k : 'b Step + static member (>>=) ( Priority1, a : 'a Async) = fun (k: 'a -> 'b Step) -> bindTask (Async.StartAsTask a) k : 'b Step + + type ReturnFromS = Priority1 with + static member inline ($) (Priority1, taskLike ) = Binder<_>.GenericAwait (taskLike, ret) + static member ($) (Priority1, a : 'a Async) = bindTask (Async.StartAsTask a) ret : Step<'a> + + type BindI = Priority1 with + static member inline (>>=) (_:Priority3, taskLike : 't) = fun (k : _ -> 'b Step) -> Binder<'b>.GenericAwait (taskLike, k) : 'b Step + static member inline (>>=) (_:Priority2, configurableTaskLike: 't) = fun (k : _ -> 'b Step) -> Binder<'b>.GenericAwaitConfigureFalse (configurableTaskLike, k): 'b Step + static member (>>=) ( Priority1, task: 'a Task ) = fun (k : 'a -> 'b Step) -> bindTaskConfigureFalse task k : 'b Step + static member (>>=) ( Priority1, a : 'a Async ) = fun (k : 'a -> 'b Step) -> bindTaskConfigureFalse (Async.StartAsTask a) k : 'b Step + + type ReturnFromI = Priority1 with + static member inline ($) (_:Priority2, taskLike ) = Binder<_>.GenericAwait(taskLike, ret) + static member inline ($) ( Priority1, configurableTaskLike) = Binder<_>.GenericAwaitConfigureFalse(configurableTaskLike, ret) + static member ($) ( Priority1, a : 'a Async ) = bindTaskConfigureFalse (Async.StartAsTask a) ret + + // New style task builder. + type TaskBuilderV2() = + // These methods are consistent between all builders. + member __.Delay(f : unit -> Step<_>) = f + member __.Run(f : unit -> Step<'m>) = run f + member __.Zero() = zero + member __.Return(x) = ret x + member __.Combine(step : unit Step, continuation) = combine step continuation + member __.While(condition : unit -> bool, body : unit -> unit Step) = whileLoop condition body + member __.For(sequence : _ seq, body : _ -> unit Step) = forLoop sequence body + member __.TryWith(body : unit -> _ Step, catch : exn -> _ Step) = tryWith body catch + member __.TryFinally(body : unit -> _ Step, fin : unit -> unit) = tryFinally body fin + member __.Using(disp : #IDisposable, body : #IDisposable -> _ Step) = using disp body + member __.ReturnFrom a : _ Step = ReturnFrom a + + // Old style task builder. Retained for binary compatibility. + type TaskBuilder() = + // These methods are consistent between the two builders. + // Unfortunately, inline members do not work with inheritance. + member inline __.Delay(f : unit -> Step<_>) = f + member inline __.Run(f : unit -> Step<'m>) = run f + member inline __.Zero() = zero + member inline __.Return(x) = ret x + member inline __.Combine(step : unit Step, continuation) = combine step continuation + member inline __.While(condition : unit -> bool, body : unit -> unit Step) = whileLoop condition body + member inline __.For(sequence : _ seq, body : _ -> unit Step) = forLoop sequence body + member inline __.TryWith(body : unit -> _ Step, catch : exn -> _ Step) = tryWith body catch + member inline __.TryFinally(body : unit -> _ Step, fin : unit -> unit) = tryFinally body fin + member inline __.Using(disp : #IDisposable, body : #IDisposable -> _ Step) = using disp body + // End of consistent methods -- the following methods are different between + // `TaskBuilder` and `ContextInsensitiveTaskBuilder`! + + // We have to have a dedicated overload for Task<'a> so the compiler doesn't get confused. + // Everything else can use bindGenericAwaitable via an extension member (defined later). + member inline __.ReturnFrom(task : _ Task) = ReturnFrom task + member inline __.Bind(task : 'a Task, continuation : 'a -> 'b Step) : 'b Step = + bindTask task continuation + + // Old style task builder. Retained for binary compatibility. + type ContextInsensitiveTaskBuilder() = + // These methods are consistent between the two builders. + // Unfortunately, inline members do not work with inheritance. + member inline __.Delay(f : unit -> Step<_>) = f + member inline __.Run(f : unit -> Step<'m>) = run f + member inline __.Zero() = zero + member inline __.Return(x) = ret x + member inline __.Combine(step : unit Step, continuation) = combine step continuation + member inline __.While(condition : unit -> bool, body : unit -> unit Step) = whileLoop condition body + member inline __.For(sequence : _ seq, body : _ -> unit Step) = forLoop sequence body + member inline __.TryWith(body : unit -> _ Step, catch : exn -> _ Step) = tryWith body catch + member inline __.TryFinally(body : unit -> _ Step, fin : unit -> unit) = tryFinally body fin + member inline __.Using(disp : #IDisposable, body : #IDisposable -> _ Step) = using disp body + // End of consistent methods -- the following methods are different between + // `TaskBuilder` and `ContextInsensitiveTaskBuilder`! + + // We have to have a dedicated overload for Task<'a> so the compiler doesn't get confused. + // Everything else can use bindGenericAwaitable via an extension member (defined later). + member inline __.ReturnFrom(task : _ Task) = ReturnFrom task + member inline __.Bind(task : 'a Task, continuation : 'a -> 'b Step) : 'b Step = + bindTaskConfigureFalse task continuation + + +// Don't warn about our use of the "obsolete" module we just defined (see notes at start of file). +#nowarn "44" + +[] +module ContextSensitive = + /// Builds a `System.Threading.Tasks.Task<'a>` similarly to a C# async/await method. + /// Use this like `task { let! taskResult = someTask(); return taskResult.ToString(); }`. + let taskBuilder = TaskBuilder.TaskBuilder() + + [] + let inline unitTask t = t :> Task + + // These are fallbacks when the Bind and ReturnFrom on the builder object itself don't apply. + // This is how we support binding arbitrary task-like types. + type TaskBuilder.TaskBuilder with + member inline this.ReturnFrom(taskLike) = + TaskBuilder.Binder<_>.GenericAwait(taskLike, TaskBuilder.ret) + member inline this.Bind(taskLike, continuation : _ -> 'a TaskBuilder.Step) : 'a TaskBuilder.Step = + TaskBuilder.Binder<'a>.GenericAwait(taskLike, continuation) + // Convenience overloads for Asyncs. + member __.ReturnFrom(a : 'a Async) = + TaskBuilder.bindTask (Async.StartAsTask a) TaskBuilder.ret + member __.Bind(a : 'a Async, continuation : 'a -> 'b TaskBuilder.Step) : 'b TaskBuilder.Step = + TaskBuilder.bindTask (Async.StartAsTask a) continuation + +module ContextInsensitive = + /// Builds a `System.Threading.Tasks.Task<'a>` similarly to a C# async/await method, but with + /// all awaited tasks automatically configured *not* to resume on the captured context. + /// This is often preferable when writing library code that is not context-aware, but undesirable when writing + /// e.g. code that must interact with user interface controls on the same thread as its caller. + let task = TaskBuilder.ContextInsensitiveTaskBuilder() + + [] + let inline unitTask (t : Task) = t.ConfigureAwait(false) + + // These are fallbacks when the Bind and ReturnFrom on the builder object itself don't apply. + // This is how we support binding arbitrary task-like types. + type TaskBuilder.ContextInsensitiveTaskBuilder with + member inline this.ReturnFrom(taskLike) = + TaskBuilder.Binder<_>.GenericAwait(taskLike, TaskBuilder.ret) + member inline this.Bind(taskLike, continuation : _ -> 'a TaskBuilder.Step) : 'a TaskBuilder.Step = + TaskBuilder.Binder<'a>.GenericAwait(taskLike, continuation) + + // Convenience overloads for Asyncs. + member __.ReturnFrom(a : 'a Async) = + TaskBuilder.bindTaskConfigureFalse (Async.StartAsTask a) TaskBuilder.ret + member __.Bind(a : 'a Async, continuation : 'a -> 'b TaskBuilder.Step) : 'b TaskBuilder.Step = + TaskBuilder.bindTaskConfigureFalse (Async.StartAsTask a) continuation + + [] + module HigherPriorityBinds = + // When it's possible for these to work, the compiler should prefer them since they shadow the ones above. + type TaskBuilder.ContextInsensitiveTaskBuilder with + member inline this.ReturnFrom(configurableTaskLike) = + TaskBuilder.Binder<_>.GenericAwaitConfigureFalse(configurableTaskLike, TaskBuilder.ret) + member inline this.Bind(configurableTaskLike, continuation : _ -> 'a TaskBuilder.Step) : 'a TaskBuilder.Step = + TaskBuilder.Binder<'a>.GenericAwaitConfigureFalse(configurableTaskLike, continuation) + + +module V2 = + [] + module ContextSensitive = + open TaskBuilder + + /// Builds a `System.Threading.Tasks.Task<'a>` similarly to a C# async/await method. + /// Use this like `task { let! taskResult = someTask(); return taskResult.ToString(); }`. + let taskBuilder = TaskBuilderV2() + + [] + let unitTask (t : Task) = t + + type TaskBuilderV2 with + member inline __.Bind (task, continuation : 'a -> 'b Step) : 'b Step = (BindS.Priority1 >>= task) continuation + member inline __.ReturnFrom a : 'b Step = ReturnFromS.Priority1 $ a + + module ContextInsensitive = + open TaskBuilder + + /// Builds a `System.Threading.Tasks.Task<'a>` similarly to a C# async/await method, but with + /// all awaited tasks automatically configured *not* to resume on the captured context. + /// This is often preferable when writing library code that is not context-aware, but undesirable when writing + /// e.g. code that must interact with user interface controls on the same thread as its caller. + let task = TaskBuilderV2() + + [] + let unitTask (t : Task) = t.ConfigureAwait(false) + + type TaskBuilderV2 with + member inline __.Bind (task, continuation : 'a -> 'b Step) : 'b Step = (BindI.Priority1 >>= task) continuation + member inline __.ReturnFrom a : 'b Step = ReturnFromI.Priority1 $ a \ No newline at end of file diff --git a/tests/benchmarks/TaskPerf/TaskPerf.fs b/tests/benchmarks/TaskPerf/TaskPerf.fs new file mode 100644 index 00000000000..5feafc4a3da --- /dev/null +++ b/tests/benchmarks/TaskPerf/TaskPerf.fs @@ -0,0 +1,476 @@ +(* +msbuild tests\fsharp\perf\tasks\FS\TaskPerf.fsproj /p:Configuration=Release +dotnet artifacts\bin\TaskPerf\Release\netcoreapp2.1\TaskPerf.dll +*) + +namespace TaskPerf + +//open FSharp.Control.Tasks +open System +open System.Diagnostics +open System.Threading.Tasks +open System.IO +open BenchmarkDotNet.Attributes +open BenchmarkDotNet.Running +open TaskBuilderTasks //.ContextSensitive // TaskBuilder.fs extension members +//open FSharp.Control.ContextSensitiveTasks // the default +open FSharp.Control // AsyncSeq +open Tests.SyncBuilder +open BenchmarkDotNet.Configs +#if PREVIEW +open FSharp.Control.Async2 +open Tests.TaskSeq +#endif + +[] +module Helpers = + let bufferSize = 128 + let manyIterations = 1000 + let syncTask() = Task.FromResult 100 + let syncTask_async() = async.Return 100 + let syncTask_async2() = Task.FromResult 100 + let asyncYield() = Async.Sleep(0) + let asyncTask() = Task.Yield() + + let tenBindSync_taskBuilder() = + taskBuilder { + let! res1 = syncTask() + let! res2 = syncTask() + let! res3 = syncTask() + let! res4 = syncTask() + let! res5 = syncTask() + let! res6 = syncTask() + let! res7 = syncTask() + let! res8 = syncTask() + let! res9 = syncTask() + let! res10 = syncTask() + return res1 + res2 + res3 + res4 + res5 + res6 + res7 + res8 + res9 + res10 + } + + let tenBindSync_async() = + async { + let! res1 = syncTask_async() + let! res2 = syncTask_async() + let! res3 = syncTask_async() + let! res4 = syncTask_async() + let! res5 = syncTask_async() + let! res6 = syncTask_async() + let! res7 = syncTask_async() + let! res8 = syncTask_async() + let! res9 = syncTask_async() + let! res10 = syncTask_async() + return res1 + res2 + res3 + res4 + res5 + res6 + res7 + res8 + res9 + res10 + } + +#if PREVIEW + let tenBindSync_task() = + task { + let! res1 = syncTask() + let! res2 = syncTask() + let! res3 = syncTask() + let! res4 = syncTask() + let! res5 = syncTask() + let! res6 = syncTask() + let! res7 = syncTask() + let! res8 = syncTask() + let! res9 = syncTask() + let! res10 = syncTask() + return res1 + res2 + res3 + res4 + res5 + res6 + res7 + res8 + res9 + res10 + } + + let tenBindSync_async2() = + async2 { + let! res1 = syncTask_async2() + let! res2 = syncTask_async2() + let! res3 = syncTask_async2() + let! res4 = syncTask_async2() + let! res5 = syncTask_async2() + let! res6 = syncTask_async2() + let! res7 = syncTask_async2() + let! res8 = syncTask_async2() + let! res9 = syncTask_async2() + let! res10 = syncTask_async2() + return res1 + res2 + res3 + res4 + res5 + res6 + res7 + res8 + res9 + res10 + } +#endif + + let tenBindAsync_taskBuilder() = + taskBuilder { + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + } + + let tenBindAsync_async() = + async { + do! asyncYield() + do! asyncYield() + do! asyncYield() + do! asyncYield() + do! asyncYield() + do! asyncYield() + do! asyncYield() + do! asyncYield() + do! asyncYield() + do! asyncYield() + } +#if PREVIEW + let tenBindAsync_task() = + task { + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + } + + let tenBindAsync_async2() = + async2 { + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + do! asyncTask() + } +#endif + + let singleTask_taskBuilder() = + taskBuilder { return 1 } + + let singleTask_async() = + async { return 1 } +#if PREVIEW + let singleTask_task() = + task { return 1 } + + let singleTask_async2() = + async2 { return 1 } +#endif + +[] +[] +[] +type Benchmarks() = + + [] + member _.ManyWriteFile_CSharpTasks () = + TaskPerfCSharp.ManyWriteFileAsync(manyIterations).Wait(); + + [] + member _.ManyWriteFile_taskBuilder () = + let path = Path.GetTempFileName() + taskBuilder { + let junk = Array.zeroCreate bufferSize + use file = File.Create(path) + for i = 1 to manyIterations do + do! file.WriteAsync(junk, 0, junk.Length) + } + |> fun t -> t.Wait() + File.Delete(path) + + [] + member _.ManyWriteFile_async () = + let path = Path.GetTempFileName() + async { + let junk = Array.zeroCreate bufferSize + use file = File.Create(path) + for i = 1 to manyIterations do + do! Async.AwaitTask(file.WriteAsync(junk, 0, junk.Length)) + } + |> Async.RunSynchronously + File.Delete(path) + +#if PREVIEW + [] + member _.ManyWriteFile_task () = + let path = Path.GetTempFileName() + task { + let junk = Array.zeroCreate bufferSize + use file = File.Create(path) + for i = 1 to manyIterations do + do! file.WriteAsync(junk, 0, junk.Length) + } + |> fun t -> t.Wait() + File.Delete(path) + + [] + member _.ManyWriteFile_async2 () = + let path = Path.GetTempFileName() + async2 { + let junk = Array.zeroCreate bufferSize + use file = File.Create(path) + for i = 1 to manyIterations do + do! file.WriteAsync(junk, 0, junk.Length) + } + |> Async2.RunSynchronously + File.Delete(path) +#endif + + + + [] + member _.NonAsyncBinds_CSharpTasks() = + for i in 1 .. manyIterations*100 do + TaskPerfCSharp.TenBindsSync_CSharp().Wait() + + [] + member _.NonAsyncBinds_taskBuilder() = + for i in 1 .. manyIterations*100 do + tenBindSync_taskBuilder().Wait() + + [] + member _.NonAsyncBinds_async() = + for i in 1 .. manyIterations*100 do + tenBindSync_async() |> Async.RunSynchronously |> ignore + +#if PREVIEW + [] + member _.NonAsyncBinds_async2() = + for i in 1 .. manyIterations*100 do + tenBindSync_async2() |> Async2.RunSynchronously |> ignore + + [] + member _.NonAsyncBinds_task() = + for i in 1 .. manyIterations*100 do + tenBindSync_task().Wait() + +#endif + + + + + [] + member _.AsyncBinds_CSharpTasks() = + for i in 1 .. manyIterations do + TaskPerfCSharp.TenBindsAsync_CSharp().Wait() + + [] + member _.AsyncBinds_taskBuilder() = + for i in 1 .. manyIterations do + tenBindAsync_taskBuilder().Wait() + + [] + member _.AsyncBinds_async() = + for i in 1 .. manyIterations do + tenBindAsync_async() |> Async.RunSynchronously + +#if PREVIEW + [] + member _.AsyncBinds_task() = + for i in 1 .. manyIterations do + tenBindAsync_task().Wait() + + [] + member _.AsyncBinds_async2() = + for i in 1 .. manyIterations do + tenBindAsync_async2() |> Async2.RunSynchronously +#endif + + + [] + member _.SingleSyncTask_CSharpTasks() = + for i in 1 .. manyIterations*500 do + TaskPerfCSharp.SingleSyncTask_CSharp().Wait() + + [] + member _.SingleSyncTask_taskBuilder() = + for i in 1 .. manyIterations*500 do + singleTask_taskBuilder().Wait() + + [] + member _.SingleSyncTask_async() = + for i in 1 .. manyIterations*500 do + singleTask_async() |> Async.RunSynchronously |> ignore + +#if PREVIEW + [] + member _.SingleSyncTask_task() = + for i in 1 .. manyIterations*500 do + singleTask_task().Wait() + + [] + member _.SingleSyncTask_async2() = + for i in 1 .. manyIterations*500 do + singleTask_async2() |> Async2.RunSynchronously |> ignore +#endif + + [] + member _.SyncBuilderLoop_NormalCode() = + for i in 1 .. manyIterations do + let mutable res = 0 + for i in Seq.init 1000 id do + res <- i + res + + [] + member _.SyncBuilderLoop_WorkflowCode() = + for i in 1 .. manyIterations do + sync { let mutable res = 0 + for i in Seq.init 1000 id do + res <- i + res } + +#if FSHARP_CORE_HAS_LIST_COLLECTOR + [] + member _.TinyVariableSizedList_Builtin() = Tests.ListBuilders.Examples.tinyVariableSizeBuiltin() + + + [] + member _.TinyVariableSizedList_NewBuilder() = Tests.ListBuilders.Examples.tinyVariableSizeNew() + + + [] + member _.VariableSizedList_Builtin() = Tests.ListBuilders.Examples.variableSizeBuiltin() + + [] + member _.VariableSizedList_NewBuilder() = Tests.ListBuilders.Examples.variableSizeNew() + + + [] + member _.FixedSizeList_Builtin() = Tests.ListBuilders.Examples.fixedSizeBase() + + [] + member _.FixedSizeList_NewBuilder() = Tests.ListBuilders.Examples.fixedSizeC() +#endif + + [] + member _.TinyVariableSizedArray_Builtin() = Tests.ArrayBuilders.Examples.tinyVariableSizeBuiltin() + + [] + member _.TinyVariableSizedArray_NewBuilder() = Tests.ArrayBuilders.Examples.tinyVariableSizeNew() + + + [] + member _.VariableSizedArray_Builtin() = Tests.ArrayBuilders.Examples.variableSizeBuiltin() + + [] + member _.VariableSizedArray_NewBuilder() = Tests.ArrayBuilders.Examples.variableSizeNew() + + + [] + member _.FixedSizeArray_Builtin() = Tests.ArrayBuilders.Examples.fixedSizeBase() + + + [] + member _.FixedSizeArray_NewBuilder() = Tests.ArrayBuilders.Examples.fixedSizeC() + + + [] + member _.MultiStepOption_OldBuilder() = Tests.OptionBuilders.Examples.multiStepOldBuilder() + + [] + member _.MultiStepOption_NewBuilder() = Tests.OptionBuilders.Examples.multiStepNewBuilder() + + [] + member _.MultiStepOption_NoBuilder() = Tests.OptionBuilders.Examples.multiStepNoBuilder() + + + [] + member _.MultiStepValueOption_OldBuilder() = Tests.OptionBuilders.Examples.multiStepOldBuilderV() + + [] + member _.MultiStepValueOption_NewBuilder() = Tests.OptionBuilders.Examples.multiStepNewBuilderV() + + [] + member _.MultiStepValueOption_NoBuilder() = Tests.OptionBuilders.Examples.multiStepNoBuilderV() + + +#if PREVIEW + [] + member _.NestedForLoops_CSharpAsyncEnumerable() = + TaskPerfCSharp.perf2_AsyncEnumerable() |> TaskSeq.iter ignore + + [] + member _.NestedForLoops_taskSeq() = + Tests.TaskSeq.Examples.perf2() |> TaskSeq.iter ignore + + //[] + //member _.NestedForLoops_asyncSeq() = + // Tests.TaskSeq.Examples.perf2_AsyncSeq() |> AsyncSeq.iter ignore |> Async.RunSynchronously + +#endif + +module Main = + + [] + let main argv = + let require x msg = if not x then failwith msg + printfn "Testing that the tests run..." + printfn "Running testUsing..." + let f () = + let mutable disposed = 0 + let t = + task { + use d = + { new IAsyncDisposable with + member __.DisposeAsync() = + task { + disposed <- disposed + 1 + printfn $"in disposal, disposed = {disposed}" + do! Task.Delay(10) + disposed <- disposed + 1 + printfn $"after disposal, disposed = {disposed}" + } + |> ValueTask + } + printfn $"in using, disposed = {disposed}" + do! Task.Delay(10) + } + + printfn $"outside using, disposed = {disposed}" + t.Wait() + printfn $"after full disposal, disposed = {disposed}" + + f() + + //Benchmarks().SingleSyncTask_async2() + //Benchmarks().NonAsyncBinds_async2() + //Benchmarks().ManyWriteFile_CSharpTasks() + //Benchmarks().ManyWriteFile_task () + //Benchmarks().ManyWriteFile_taskBuilder () + //Benchmarks().ManyWriteFile_FSharpAsync () + //Benchmarks().NonAsyncBinds_CSharpTasks() + //Benchmarks().NonAsyncBinds_task() + //Benchmarks().NonAsyncBinds_taskBuilder() + //Benchmarks().NonAsyncBinds_FSharpAsync() + //Benchmarks().AsyncBinds_CSharpTasks() + //Benchmarks().AsyncBinds_task() + //Benchmarks().AsyncBinds_taskBuilder() + //Benchmarks().SingleSyncTask_CSharpTasks() + //Benchmarks().SingleSyncTask_task() + //Benchmarks().SingleSyncTask_taskBuilder() + //Benchmarks().SingleSyncTask_FSharpAsync() + + //printfn "Sample t1..." + //Tests.akSeqBuilder.Examples.t1() |> TaskSeq.iter (printfn "t1(): %s") + //printfn "Sample t2..." + //Tests.TaskSeqBuilder.Examples.t2() |> TaskSeq.iter (printfn "t2(): %s") + //printfn "Sample perf1(2)..." + //Tests.TaskSeqBuilder.Examples.perf1(2) |> TaskSeq.iter (printfn "perf1(2): %d") + //printfn "Sample perf1(3)..." + //Tests.TaskSeqBuilder.Examples.perf1(3) |> TaskSeq.iter (printfn "perf1(3): %d") + //printfn "Sample perf2..." + //Tests.TaskSeqBuilder.Examples.perf2() |> TaskSeq.iter (printfn "perf2: %d") + + //Tests.TaskSeq.Examples.perf2_AsyncSeq() |> AsyncSeq.toArrayAsync |> Async.RunSynchronously |> Array.sum |> (printf "%d."); printfn "" + //Tests.TaskSeq.Examples.perf2() |> TaskSeq.toArray |> Array.sum |> (printfn "%d.") + //TaskPerfCSharp.perf2_AsyncEnumerable() |> TaskSeq.toArray |> Array.sum |> (printfn "%d.") + + printfn "Running benchmarks..." + let results = BenchmarkRunner.Run() + 0 \ No newline at end of file diff --git a/tests/benchmarks/TaskPerf/TaskPerf.fsproj b/tests/benchmarks/TaskPerf/TaskPerf.fsproj new file mode 100644 index 00000000000..88e9af5c263 --- /dev/null +++ b/tests/benchmarks/TaskPerf/TaskPerf.fsproj @@ -0,0 +1,44 @@ + + + + net5.0 + Exe + true + + $(OtherFlags) --nowarn:1204 + + $(OtherFlags) --nowarn:57 + + + $(OtherFlags) --nowarn:3511 --nowarn:3513 + $(OtherFlags) --langversion:preview + $(OtherFlags) --define:PREVIEW + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/benchmarks/TaskPerf/array.fs b/tests/benchmarks/TaskPerf/array.fs new file mode 100644 index 00000000000..8c1409f1233 --- /dev/null +++ b/tests/benchmarks/TaskPerf/array.fs @@ -0,0 +1,192 @@ + +module Tests.ArrayBuilders + +open System +open System.Collections.Generic + +[] +module UsingInlinedCodeAndCollector = + + [] + type ArrayBuilderCollector<'T> = + [] + val mutable Result : ResizeArray<'T> + + member sm.Yield (value: 'T) = + match sm.Result with + | null -> + let ra = ResizeArray() + sm.Result <- ra + ra.Add(value) + | ra -> ra.Add(value) + + member sm.ToResizeArray() = + match sm.Result with + | null -> ResizeArray() + | ra -> ra + + member sm.ToArray() = + match sm.Result with + | null -> Array.empty + | ra -> ra.ToArray() + + type ArrayBuilderCode<'T> = delegate of byref> -> unit + + type ArrayBuilderViaCollector() = + + member inline _.Delay([] f: unit -> ArrayBuilderCode<'T>) : ArrayBuilderCode<'T> = + ArrayBuilderCode<_>(fun sm -> (f()).Invoke &sm) + + member inline _.Zero() : ArrayBuilderCode<'T> = + ArrayBuilderCode<_>(fun _sm -> ()) + + member inline _.Combine([] part1: ArrayBuilderCode<'T>, [] part2: ArrayBuilderCode<'T>) : ArrayBuilderCode<'T> = + ArrayBuilderCode<_>(fun sm -> + part1.Invoke &sm + part2.Invoke &sm) + + member inline _.While([] condition : unit -> bool, [] body : ArrayBuilderCode<'T>) : ArrayBuilderCode<'T> = + ArrayBuilderCode<_>(fun sm -> + while condition() do + body.Invoke &sm) + + member inline _.TryWith([] body: ArrayBuilderCode<'T>, [] handler: exn -> ArrayBuilderCode<'T>) : ArrayBuilderCode<'T> = + ArrayBuilderCode<_>(fun sm -> + try + body.Invoke &sm + with exn -> + (handler exn).Invoke &sm) + + member inline _.TryFinally([] body: ArrayBuilderCode<'T>, compensation : unit -> unit) : ArrayBuilderCode<'T> = + ArrayBuilderCode<_>(fun sm -> + try + body.Invoke &sm + with _ -> + compensation() + reraise() + + compensation()) + + member inline b.Using(disp : #IDisposable, [] body: #IDisposable -> ArrayBuilderCode<'T>) : ArrayBuilderCode<'T> = + // A using statement is just a try/finally with the finally block disposing if non-null. + b.TryFinally( + (fun sm -> (body disp).Invoke &sm), + (fun () -> if not (isNull (box disp)) then disp.Dispose())) + + member inline b.For(sequence: seq<'TElement>, [] body: 'TElement -> ArrayBuilderCode<'T>) : ArrayBuilderCode<'T> = + b.Using (sequence.GetEnumerator(), + (fun e -> b.While((fun () -> e.MoveNext()), (fun sm -> (body e.Current).Invoke &sm)))) + + member inline _.Yield (v: 'T) : ArrayBuilderCode<'T> = + ArrayBuilderCode<_>(fun sm -> + sm.Yield v) + + member inline b.YieldFrom (source: IEnumerable<'T>) : ArrayBuilderCode<'T> = + b.For(source, (fun value -> b.Yield(value))) + + member inline _.Run([] code: ArrayBuilderCode<'T>) : 'T[] = + let mutable sm = ArrayBuilderCollector<'T>() + code.Invoke &sm + sm.ToArray() + + let arrayNew = ArrayBuilderViaCollector() + +module Examples = + + let tinyVariableSizeNew () = + for i in 1 .. 1000000 do + arrayNew { + if i % 3 = 0 then + yield "b" + } |> Array.length |> ignore + + let tinyVariableSizeBuiltin () = + for i in 1 .. 1000000 do + [| + if i % 3 = 0 then + yield "b" + |] |> Array.length |> ignore + + let variableSizeNew () = + for i in 1 .. 1000000 do + arrayNew { + yield "a" + yield "b" + yield "b" + yield "b" + yield "b" + if i % 3 = 0 then + yield "b" + yield "b" + yield "b" + yield "b" + yield "c" + } |> Array.length |> ignore + + let variableSizeBuiltin () = + for i in 1 .. 1000000 do + [| + yield "a" + yield "b" + yield "b" + yield "b" + yield "b" + if i % 3 = 0 then + yield "b" + yield "b" + yield "b" + yield "b" + yield "c" + |] |> Array.length |> ignore + + let fixedSizeC () = + for i in 1 .. 1000000 do + arrayNew { + "a" + "b" + "b" + "b" + "b" + "b" + "b" + "b" + "b" + "c" + } |> Array.length |> ignore + + let fixedSizeBase () = + for i in 1 .. 1000000 do + [| + "a" + "b" + "b" + "b" + "b" + "b" + "b" + "b" + "b" + "c" + |] |> Array.length |> ignore + + let perf s f = + let t = System.Diagnostics.Stopwatch() + t.Start() + f() + t.Stop() + printfn "PERF: %s : %d" s t.ElapsedMilliseconds + + perf "tinyVariableSizeBuiltin" tinyVariableSizeBuiltin + perf "tinyVariableSizeNew " tinyVariableSizeNew + + perf "variableSizeBuiltin" variableSizeBuiltin + perf "variableSizeNew" variableSizeNew + + perf "fixedSizeBase" fixedSizeBase + perf "fixedSizeC" fixedSizeC + // let dumpSeq (t: IEnumerable<_>) = + // let e = t.GetEnumerator() + // while e.MoveNext() do + // printfn "yield %A" e.Current + // dumpSeq (t1()) + // dumpSeq (t2()) diff --git a/tests/benchmarks/TaskPerf/async2.fs b/tests/benchmarks/TaskPerf/async2.fs new file mode 100644 index 00000000000..06938716ae1 --- /dev/null +++ b/tests/benchmarks/TaskPerf/async2.fs @@ -0,0 +1,1131 @@ + +namespace FSharp.Control.Async2 + +open System.Runtime.CompilerServices + +#nowarn "42" +open System +open System.Threading +open System.Threading.Tasks +open FSharp.Core.CompilerServices +open FSharp.Core.CompilerServices.StateMachineHelpers + +[] +module Utils = + let verbose = false + + let inline MoveNext(x: byref<'T> when 'T :> IAsyncStateMachine) = x.MoveNext() + +[] +type Async2StateMachineData<'T>() = + [] + val mutable cancellationToken : CancellationToken + [] + val mutable result : 'T + [] + val mutable builder : AsyncTaskMethodBuilder<'T> + [] + val mutable taken : bool + //// For tailcalls using 'return!' + //[] + //val mutable tailcallTarget: IAsync2Invocation<'T> + +and IAsync2Invokable<'T> = + abstract StartImmediate: CancellationToken -> IAsync2Invocation<'T> + +and [] IAsync2Invocation<'T> = + inherit IAsyncStateMachine + //abstract TailcallTarget: IAsync2Invocation<'T> + abstract CancellationToken: CancellationToken + abstract Task: Task<'T> + +and [] + Async2<'T>() = + + // F# requires that we implement interfaces even on an abstract class + interface IAsync2Invokable<'T> with + member _.StartImmediate(ct) = failwith "abstract" + + interface IAsync2Invocation<'T> with + //member _.TailcallTarget = failwith "abstract" + member _.CancellationToken = failwith "abstract" + member _.Task = failwith "abstract" + interface IAsyncStateMachine with + member _.MoveNext() = failwith "abstract" + member _.SetStateMachine(_state) = failwith "abstract" + + member inline x.StartImmediate(ct) = (x :> IAsync2Invokable<'T>).StartImmediate(ct) + +and [] + Async2<'Machine, 'T when 'Machine :> IAsyncStateMachine and 'Machine :> IResumableStateMachine>>() = + inherit Async2<'T>() + let initialThreadId = Environment.CurrentManagedThreadId + + [] + val mutable Machine : 'Machine + + //member internal ts.hijack() = (ts :> IAsync2Invocation<_>) + //let res = ts.Machine.Data.tailcallTarget + //match res with + //| null -> (ts :> IAsync2Invocation<_>) + //| tg -> + // match (tg :> IAsync2Invocation<_>).TailcallTarget with + // | null -> + // res + // | res2 -> + // // Cut out chains of tailcalls + // ts.Machine.Data.tailcallTarget <- res2 + // res2 + + interface IAsyncStateMachine with + member ts.MoveNext() = + MoveNext(&ts.Machine) + + //match ts.hijack() with + //| null -> + //| tg -> (tg :> IAsyncStateMachine).MoveNext() + + member ts.SetStateMachine(state) = + //printfn "SetStateMachine" + () + //ts.Machine.Data.builder.SetStateMachine(state) + + interface IAsync2Invokable<'T> with + member ts.StartImmediate(ct) = + let data = ts.Machine.Data + if (not data.taken && initialThreadId = Environment.CurrentManagedThreadId) then + data.taken <- true + data.cancellationToken <- ct + //printfn "creating" + data.builder <- AsyncTaskMethodBuilder<'T>.Create() + //printfn "starting" + data.builder.Start(&ts.Machine) + (ts :> IAsync2Invocation<_>) + else + let clone = ts.MemberwiseClone() :?> Async2<'Machine, 'T> + data.taken <- true + clone.Machine.Data.cancellationToken <- ct + clone.Machine.MoveNext() + (clone :> IAsync2Invocation<'T>) + + interface IAsync2Invocation<'T> with + member ts.CancellationToken = ts.Machine.Data.cancellationToken + member ts.Task = ts.Machine.Data.builder.Task + //member ts.TailcallTarget = ts.hijack() + +and Async2Code<'TOverall, 'T> = ResumableCode, 'T> +and Async2StateMachine<'T> = ResumableStateMachine> +and Async2ResumptionFunc<'T> = ResumptionFunc> +and Async2ResumptionDynamicInfo<'T> = ResumptionDynamicInfo> + +[] +type Async2Builder() = + + member inline _.Delay(f : unit -> Async2Code<'TOverall, 'T>) : Async2Code<'TOverall, 'T> = + Async2Code<'TOverall, 'T>(fun sm -> f().Invoke(&sm)) + + member inline _.Run(code : Async2Code<'T, 'T>) : Async2<'T> = + if __useResumableCode then + // This is the static implementation. A new struct type is created. + __stateMachine, Async2<'T>> + (MoveNextMethodImpl<_>(fun sm -> + //-- RESUMABLE CODE START + __resumeAt sm.ResumptionPoint + try + //printfn "at Run.MoveNext start" + //Console.WriteLine("[{0}] resuming by invoking {1}....", sm.MethodBuilder.Task.Id, hashq sm.ResumptionFunc ) + let __stack_code_fin = code.Invoke(&sm) + //printfn $"at Run.MoveNext, __stack_code_fin={__stack_code_fin}" + if __stack_code_fin then + //printfn $"at Run.MoveNext, done" + sm.Data.builder.SetResult(sm.Data.result) + + with exn -> + //Console.WriteLine("[{0}] SetException {1}", sm.MethodBuilder.Task.Id, exn) + sm.Data.builder.SetException(exn) + + //// tailcall + //match sm.Data.tailcallTarget with + //| null -> + // printfn $"at Run.MoveNext, await" + //| tg -> + // printfn $"at Run.MoveNext, hijack" + // let mutable tg = tg + // MoveNext(&tg) + //-- RESUMABLE CODE END + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> + let ts = Async2, 'T>() + ts.Machine <- sm + ts.Machine.Data <- Async2StateMachineData() + ts :> Async2<'T>)) + else + failwith "no dynamic implementation as yet" + // let initialResumptionFunc = Async2ResumptionFunc<'T>(fun sm -> code.Invoke(&sm)) + // let resumptionFuncExecutor = Async2ResumptionExecutor<'T>(fun sm f -> + // // TODO: add exception handling? + // if f.Invoke(&sm) then + // sm.ResumptionPoint <- -2) + // let setStateMachine = SetStateMachineMethodImpl<_>(fun sm f -> ()) + // sm.Machine.ResumptionFuncInfo <- (initialResumptionFunc, resumptionFuncExecutor, setStateMachine) + //sm.Start() + + + [] + member inline _.Zero() : Async2Code<'TOverall, unit> = + ResumableCode.Zero() + + member inline _.Combine(task1: Async2Code<'TOverall, unit>, task2: Async2Code<'TOverall, 'T>) : Async2Code<'TOverall, 'T> = + ResumableCode.Combine(task1, task2) + + member inline _.WhileAsync([] condition : unit -> ValueTask, body : Async2Code<'TOverall, unit>) : Async2Code<'TOverall, unit> = + let mutable condition_res = true + ResumableCode.While((fun () -> condition_res), + ResumableCode<_,_>(fun sm -> + let mutable __stack_condition_fin = true + let __stack_vtask = condition() + if __stack_vtask.IsCompleted then + __stack_condition_fin <- true + condition_res <- __stack_vtask.Result + else + let task = __stack_vtask.AsTask() + let mutable awaiter = task.GetAwaiter() + // This will yield with __stack_fin = false + // This will resume with __stack_fin = true + let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm) + __stack_condition_fin <- __stack_yield_fin + + if __stack_condition_fin then + condition_res <- task.Result + else + sm.Data.builder.AwaitUnsafeOnCompleted(&awaiter, &sm) + + if __stack_condition_fin then + if condition_res then + body.Invoke(&sm) + else + true + else + false + )) + + member inline _.While([] condition : unit -> bool, body : Async2Code<'TOverall, unit>) : Async2Code<'TOverall, unit> = + ResumableCode.While(condition, body) + + member inline _.TryWith(body : Async2Code<'TOverall, 'T>, catch : exn -> Async2Code<'TOverall, 'T>) : Async2Code<'TOverall, 'T> = + ResumableCode.TryWith(body, catch) + + member inline internal _.TryFinallyAsync(body: Async2Code<'TOverall, 'T>, compensation : unit -> Task) : Async2Code<'TOverall, 'T> = + ResumableCode.TryFinallyAsync(body, ResumableCode<_,_>(fun sm -> + let mutable __stack_condition_fin = true + let __stack_vtask = compensation() + if not __stack_vtask.IsCompleted then + let mutable awaiter = __stack_vtask.GetAwaiter() + let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm) + __stack_condition_fin <- __stack_yield_fin + + if not __stack_condition_fin then + sm.Data.builder.AwaitUnsafeOnCompleted(&awaiter, &sm) + + __stack_condition_fin)) + + member inline _.TryFinally(body: Async2Code<'TOverall, 'T>, compensation : unit -> unit) : Async2Code<'TOverall, 'T> = + ResumableCode.TryFinally(body, ResumableCode<_,_>(fun sm -> compensation(); true)) + + member inline this.Using(resource : #IAsyncDisposable, body : #IAsyncDisposable -> Async2Code<'TOverall, 'T>) : Async2Code<'TOverall, 'T> = + // A using statement is just a try/finally with the finally block disposing if non-null. + this.TryFinallyAsync( + (fun sm -> (body resource).Invoke(&sm)), + (fun () -> + if not (isNull (box resource)) then + resource.DisposeAsync().AsTask() + else + Task.CompletedTask)) + + member inline _.Return (v: 'T) : Async2Code<'T, 'T> = + Async2Code<'T, 'T>(fun sm -> + sm.Data.result <- v + true) + + member inline _.Bind (task: Task<'TResult1>, continuation: ('TResult1 -> Async2Code<'TOverall, 'T>)) : Async2Code<'TOverall, 'T> = + Async2Code<'TOverall, 'T>(fun sm -> + let mutable awaiter = task.GetAwaiter() + let mutable __stack_fin = true + if not awaiter.IsCompleted then + // This will yield with __stack_fin2 = false + // This will resume with __stack_fin2 = true + let __stack_fin2 = ResumableCode.Yield().Invoke(&sm) + __stack_fin <- __stack_fin2 + + if __stack_fin then + let result = awaiter.GetResult() + (continuation result).Invoke(&sm) + else + sm.Data.builder.AwaitUnsafeOnCompleted(&awaiter, &sm) + false) + + member inline b.Bind (computation: Async2<'TResult1>, continuation: ('TResult1 -> Async2Code<'TOverall, 'T>)) : Async2Code<'TOverall, 'T> = + Async2Code<'TOverall, 'T>(fun sm -> + let ct = sm.Data.cancellationToken + b.Bind(computation.StartImmediate(ct).Task, continuation).Invoke(&sm)) + + member inline b.Bind (computation: Async<'TResult1>, continuation: ('TResult1 -> Async2Code<'TOverall, 'T>)) : Async2Code<'TOverall, 'T> = + Async2Code<'TOverall, 'T>(fun sm -> + let ct = sm.Data.cancellationToken + b.Bind(Async.StartImmediateAsTask(computation, ct), continuation).Invoke(&sm)) + + member inline b.ReturnFrom (task: Task<'T>) : Async2Code<'T, 'T> = + // No tailcalling to tasks + b.Bind(task, (fun res -> b.Return(res))) + + member inline b.ReturnFrom (computation: Async<'T>) : Async2Code<'T, 'T> = + // No tailcalling to Async + b.Bind(computation, (fun res -> b.Return(res))) + +// TODO - implement RFC for ReturnFromTailcall to make this safe + member inline b.ReturnFrom (other: Async2<'T>) : Async2Code<'T, 'T> = + b.Bind(other, (fun res -> b.Return(res))) + //Async2Code<'T, _>(fun sm -> + // printfn "setting hijack target and starting" + // sm.Data.tailcallTarget <- other + // // For tailcalls we return 'false' and re-run from the entry (trampoline) + // false + //) + + + +[] +module Async2 = + type Async2Builder with + member inline this.Using(resource : ('TResource :> IDisposable), body : ('TResource -> Async2Code<'TOverall, 'T>)) : Async2Code<'TOverall, 'T> = + // A using statement is just a try/finally with the finally block disposing if non-null. + this.TryFinally( + (fun sm -> (body resource).Invoke(&sm)), + (fun () -> if not (isNull (box resource)) then resource.Dispose())) + + member inline _.Bind< ^TaskLike, ^TResult1, 'TResult2, ^Awaiter , 'TOverall + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> ^TResult1)> + (task: ^TaskLike, continuation: (^TResult1 -> Async2Code<'TOverall, 'TResult2>)) : Async2Code<'TOverall, 'TResult2> = + + Async2Code<'TOverall, 'TResult2>(fun sm -> + if __useResumableCode then + //-- RESUMABLE CODE START + // Get an awaiter from the awaitable + let mutable awaiter = (^TaskLike: (member GetAwaiter : unit -> ^Awaiter)(task)) + + let mutable __stack_fin = true + if not (^Awaiter : (member get_IsCompleted : unit -> bool)(awaiter)) then + // This will yield with __stack_yield_fin = false + // This will resume with __stack_yield_fin = true + let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm) + __stack_fin <- __stack_yield_fin + + if __stack_fin then + let result = (^Awaiter : (member GetResult : unit -> ^TResult1)(awaiter)) + (continuation result).Invoke(&sm) + else + sm.Data.builder.AwaitUnsafeOnCompleted(&awaiter, &sm) + false + else + failwith "dynamic" //TaskWitnesses.CanBindDynamic< ^TaskLike, ^TResult1, 'TResult2, ^Awaiter , 'TOverall>(&sm, priority, task, continuation) + //-- RESUMABLE CODE END + ) + + member inline b.ReturnFrom< ^TaskLike, ^Awaiter, ^T + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> ^T)> + (task: ^TaskLike) : Async2Code< ^T, ^T> = + b.Bind(task, (fun res -> b.Return(res))) + + member inline this.For(sequence : seq<'TElement>, body : 'TElement -> Async2Code<'TOverall, unit>) : Async2Code<'TOverall, unit> = + // A for loop is just a using statement on the sequence's enumerator... + this.Using (sequence.GetEnumerator(), + // ... and its body is a while loop that advances the enumerator and runs the body on each element. + (fun e -> this.While((fun () -> e.MoveNext()), (fun sm -> (body e.Current).Invoke(&sm))))) + + let async2 = Async2Builder() + + let runSynchronously ct (t: Async2<'T>) = + let e = t.StartImmediate(ct) + e.Task.Result + + let cancellationTokenAsync = + async2.Run(Async2Code(fun sm -> + sm.Data.result <- sm.Data.cancellationToken + true)) + + let unitAsync = async2 { return () } + +[] +type Async2 = + + static member CancellationToken = cancellationTokenAsync + + static member CancelCheck () = unitAsync + + static member DefaultCancellationToken = Async.DefaultCancellationToken + + static member CancelDefaultToken() = Async.CancelDefaultToken() + + static member Catch (computation: Async2<'T>) = + async2 { try let! res = computation in return Choice1Of2 res with e -> return Choice2Of2 e } + + static member RunSynchronously (computation: Async2<'T>, ?timeout: int, ?cancellationToken:CancellationToken) = + // TODO: timeout + let cancellationToken = defaultArg cancellationToken Async.DefaultCancellationToken + let e = computation.StartImmediate(cancellationToken) + e.Task.Result + + static member StartImmediateAsTask (computation: Async2<'T>, ?cancellationToken ) : Task<'T> = + let cancellationToken = defaultArg cancellationToken Async.DefaultCancellationToken + let e = computation.StartImmediate(cancellationToken) + e.Task + + static member StartImmediate(computation:Async2, ?cancellationToken) : unit = + let cancellationToken = defaultArg cancellationToken Async.DefaultCancellationToken + let e = computation.StartImmediate(cancellationToken) + e |> ignore + + static member SwitchToNewThread() = + async2 { return! Task.CompletedTask.ConfigureAwait(false) } + + static member SwitchToThreadPool() : Async2 = + async2 { return! Task.CompletedTask.ConfigureAwait(false) } + + static member Start (computation: Async2, ?cancellationToken) = + let p = + async2 { + do! Async2.SwitchToThreadPool() + return! computation + } + Async2.StartImmediate(p, ?cancellationToken=cancellationToken) + + static member StartAsTask (computation: Async2<'T>, ?taskCreationOptions: TaskCreationOptions, ?cancellationToken) = + // TODO: taskCreationOptions + let p = + async2 { + do! Async2.SwitchToThreadPool() + return! computation + } + Async2.StartImmediateAsTask(p, ?cancellationToken=cancellationToken) + + static member StartChildAsTask (computation: Async2<'T>, ?taskCreationOptions) : Async2> = + async2 { + let! cancellationToken = cancellationTokenAsync + return Async2.StartAsTask (computation, ?taskCreationOptions=taskCreationOptions, cancellationToken=cancellationToken) + } + + + static member Sleep (millisecondsDueTime: int64) : Async2 = + // TODO: int64 millisecondsDueTime? + async2 { return! Task.Delay(int millisecondsDueTime)} + + static member Sleep (millisecondsDueTime: int32) : Async2 = + async2 { return! Task.Delay(millisecondsDueTime)} + + static member Sleep (dueTime: TimeSpan) = + async2 { return! Task.Delay(dueTime)} + + static member Ignore (computation: Async2<'T>) = + async2 { let! _res = computation in return () } + + static member AwaitTask (task:Task<'T>) : Async2<'T> = + async2 { return! task } + + static member AwaitTask (task:Task) : Async2 = + async2 { return! task } + + //static member FromContinuations (callback: ('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) : Async2<'T> = + // MakeAsync (fun ctxt -> + // if ctxt.IsCancellationRequested then + // ctxt.OnCancellation () + // else + // let mutable underCurrentThreadStack = true + // let mutable contToTailCall = None + // let thread = Thread.CurrentThread + // let latch = Latch() + // let once cont x = + // if not(latch.Enter()) then invalidOp(SR.GetString(SR.controlContinuationInvokedMultipleTimes)) + // if Thread.CurrentThread.Equals thread && underCurrentThreadStack then + // contToTailCall <- Some(fun () -> cont x) + // else if Trampoline.ThisThreadHasTrampoline then + // let syncCtxt = SynchronizationContext.Current + // ctxt.trampolineHolder.PostOrQueueWithTrampoline syncCtxt (fun () -> cont x) |> unfake + // else + // ctxt.trampolineHolder.ExecuteWithTrampoline (fun () -> cont x ) |> unfake + // try + // callback (once ctxt.cont, (fun exn -> once ctxt.econt (ExceptionDispatchInfo.RestoreOrCapture exn)), once ctxt.ccont) + // with exn -> + // if not(latch.Enter()) then invalidOp(SR.GetString(SR.controlContinuationInvokedMultipleTimes)) + // let edi = ExceptionDispatchInfo.RestoreOrCapture exn + // ctxt.econt edi |> unfake + + // underCurrentThreadStack <- false + + // match contToTailCall with + // | Some k -> k() + // | _ -> fake()) + + //static member Parallel (computations: seq>) = Async.Parallel(computations, ?maxDegreeOfParallelism=None) + + //static member Parallel (computations: seq>, ?maxDegreeOfParallelism: int) = + // match maxDegreeOfParallelism with + // | Some x when x < 1 -> raise(System.ArgumentException(String.Format(SR.GetString(SR.maxDegreeOfParallelismNotPositive), x), "maxDegreeOfParallelism")) + // | _ -> () + + // MakeAsync (fun ctxt -> + // let tasks, result = + // try + // Seq.toArray computations, None // manually protect eval of seq + // with exn -> + // let edi = ExceptionDispatchInfo.RestoreOrCapture exn + // null, Some (ctxt.econt edi) + + // match result with + // | Some r -> r + // | None -> + // if tasks.Length = 0 then + // // must not be in a 'protect' if we call cont explicitly; if cont throws, it should unwind the stack, preserving Dev10 behavior + // ctxt.cont [| |] + // else + // ProtectedCode ctxt (fun ctxt -> + // let ctxtWithSync = DelimitSyncContext ctxt // manually resync + // let mutable count = tasks.Length + // let mutable firstExn = None + // let results = Array.zeroCreate tasks.Length + // // Attempt to cancel the individual operations if an exception happens on any of the other threads + // let innerCTS = new LinkedSubSource(ctxtWithSync.token) + + // let finishTask remaining = + // if (remaining = 0) then + // innerCTS.Dispose() + // match firstExn with + // | None -> ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.cont results) + // | Some (Choice1Of2 exn) -> ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.econt exn) + // | Some (Choice2Of2 cexn) -> ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.ccont cexn) + // else + // fake() + + // // recordSuccess and recordFailure between them decrement count to 0 and + // // as soon as 0 is reached dispose innerCancellationSource + + // let recordSuccess i res = + // results.[i] <- res + // finishTask(Interlocked.Decrement &count) + + // let recordFailure exn = + // // capture first exception and then decrement the counter to avoid race when + // // - thread 1 decremented counter and preempted by the scheduler + // // - thread 2 decremented counter and called finishTask + // // since exception is not yet captured - finishtask will fall into success branch + // match Interlocked.CompareExchange(&firstExn, Some exn, None) with + // | None -> + // // signal cancellation before decrementing the counter - this guarantees that no other thread can sneak to finishTask and dispose innerCTS + // // NOTE: Cancel may introduce reentrancy - i.e. when handler registered for the cancellation token invokes cancel continuation that will call 'recordFailure' + // // to correctly handle this we need to return decremented value, not the current value of 'count' otherwise we may invoke finishTask with value '0' several times + // innerCTS.Cancel() + // | _ -> () + // finishTask(Interlocked.Decrement &count) + + // // If maxDegreeOfParallelism is set but is higher then the number of tasks we have we set it back to None to fall into the simple + // // queue all items branch + // let maxDegreeOfParallelism = + // match maxDegreeOfParallelism with + // | None -> None + // | Some x when x >= tasks.Length -> None + // | Some _ as x -> x + + // // Simple case (no maxDegreeOfParallelism) just queue all the work, if we have maxDegreeOfParallelism set we start that many workers + // // which will make progress on the actual computations + // match maxDegreeOfParallelism with + // | None -> + // tasks |> Array.iteri (fun i p -> + // QueueAsync + // innerCTS.Token + // // on success, record the result + // (fun res -> recordSuccess i res) + // // on exception... + // (fun edi -> recordFailure (Choice1Of2 edi)) + // // on cancellation... + // (fun cexn -> recordFailure (Choice2Of2 cexn)) + // p + // |> unfake) + // | Some maxDegreeOfParallelism -> + // let mutable i = -1 + // let rec worker (trampolineHolder : TrampolineHolder) = + // if i < tasks.Length then + // let j = Interlocked.Increment &i + // if j < tasks.Length then + // if innerCTS.Token.IsCancellationRequested then + // let cexn = OperationCanceledException (innerCTS.Token) + // recordFailure (Choice2Of2 cexn) |> unfake + // worker trampolineHolder |> unfake + // else + // let taskCtxt = + // AsyncActivation.Create + // innerCTS.Token + // trampolineHolder + // (fun res -> recordSuccess j res |> unfake; worker trampolineHolder) + // (fun edi -> recordFailure (Choice1Of2 edi) |> unfake; worker trampolineHolder) + // (fun cexn -> recordFailure (Choice2Of2 cexn) |> unfake; worker trampolineHolder) + // tasks.[j].Invoke taskCtxt |> unfake + // fake() + // for x = 1 to maxDegreeOfParallelism do + // let trampolineHolder = TrampolineHolder() + // trampolineHolder.QueueWorkItemWithTrampoline (fun () -> + // worker trampolineHolder) + // |> unfake + + // fake())) + + //static member Sequential (computations: seq>) = Async.Parallel(computations, maxDegreeOfParallelism=1) + + //static member Choice(computations: Async2<'T option> seq) : Async2<'T option> = + // MakeAsync (fun ctxt -> + // let result = + // try Seq.toArray computations |> Choice1Of2 + // with exn -> ExceptionDispatchInfo.RestoreOrCapture exn |> Choice2Of2 + + // match result with + // | Choice2Of2 edi -> ctxt.econt edi + // | Choice1Of2 [||] -> ctxt.cont None + // | Choice1Of2 computations -> + // ProtectedCode ctxt (fun ctxt -> + // let ctxtWithSync = DelimitSyncContext ctxt + // let mutable count = computations.Length + // let mutable noneCount = 0 + // let mutable someOrExnCount = 0 + // let innerCts = new LinkedSubSource(ctxtWithSync.token) + + // let scont (result: 'T option) = + // let result = + // match result with + // | Some _ -> + // if Interlocked.Increment &someOrExnCount = 1 then + // innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.cont result) + // else + // fake() + + // | None -> + // if Interlocked.Increment &noneCount = computations.Length then + // innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.cont None) + // else + // fake() + + // if Interlocked.Decrement &count = 0 then + // innerCts.Dispose() + + // result + + // let econt (exn: ExceptionDispatchInfo) = + // let result = + // if Interlocked.Increment &someOrExnCount = 1 then + // innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.econt exn) + // else + // fake() + + // if Interlocked.Decrement &count = 0 then + // innerCts.Dispose() + + // result + + // let ccont (exn: OperationCanceledException) = + // let result = + // if Interlocked.Increment &someOrExnCount = 1 then + // innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.ccont exn) + // else + // fake() + + // if Interlocked.Decrement &count = 0 then + // innerCts.Dispose() + + // result + + // for c in computations do + // QueueAsync innerCts.Token scont econt ccont c |> unfake + + // fake())) + + /// StartWithContinuations, except the exception continuation is given an ExceptionDispatchInfo + //static member StartWithContinuationsUsingDispatchInfo(computation:Async2<'T>, continuation, exceptionContinuation, cancellationContinuation, ?cancellationToken) : unit = + // let cancellationToken = defaultArg cancellationToken Async.DefaultCancellationToken + // AsyncPrimitives.StartWithContinuations cancellationToken computation continuation exceptionContinuation cancellationContinuation + + //static member StartWithContinuations(computation:Async2<'T>, continuation, exceptionContinuation, cancellationContinuation, ?cancellationToken) : unit = + // Async.StartWithContinuationsUsingDispatchInfo(computation, continuation, (fun edi -> exceptionContinuation (edi.GetAssociatedSourceException())), cancellationContinuation, ?cancellationToken=cancellationToken) + + ///// Wait for a wait handle. Both timeout and cancellation are supported + //static member AwaitWaitHandle(waitHandle: WaitHandle, ?millisecondsTimeout:int) = + // let millisecondsTimeout = defaultArg millisecondsTimeout Threading.Timeout.Infinite + // if millisecondsTimeout = 0 then + // async.Delay(fun () -> + // let ok = waitHandle.WaitOne(0, exitContext=false) + // async.Return ok) + // else + // CreateDelimitedUserCodeAsync(fun ctxt -> + // let aux = ctxt.aux + // let rwh = ref (None: RegisteredWaitHandle option) + // let latch = Latch() + // let rec cancelHandler = + // Action(fun () -> + // if latch.Enter() then + // // if we got here - then we need to unregister RegisteredWaitHandle + trigger cancellation + // // entrance to TP callback is protected by latch - so savedCont will never be called + // lock rwh (fun () -> + // match !rwh with + // | None -> () + // | Some rwh -> rwh.Unregister null |> ignore) + // Async.Start (async2 { do (ctxt.ccont (OperationCanceledException(aux.token)) |> unfake) })) + + // and registration: CancellationTokenRegistration = aux.token.Register(cancelHandler) + + // let savedCont = ctxt.cont + // try + // lock rwh (fun () -> + // rwh := Some(ThreadPool.RegisterWaitForSingleObject + // (waitObject=waitHandle, + // callBack=WaitOrTimerCallback(fun _ timeOut -> + // if latch.Enter() then + // lock rwh (fun () -> rwh.Value.Value.Unregister null |> ignore) + // rwh := None + // registration.Dispose() + // ctxt.trampolineHolder.ExecuteWithTrampoline (fun () -> savedCont (not timeOut)) |> unfake), + // state=null, + // millisecondsTimeOutInterval=millisecondsTimeout, + // executeOnlyOnce=true)) + // fake()) + // with _ -> + // if latch.Enter() then + // registration.Dispose() + // reraise() // reraise exception only if we successfully enter the latch (no other continuations were called) + // else + // fake() + // ) + + //static member AwaitIAsyncResult(iar: IAsyncResult, ?millisecondsTimeout): Async2 = + // async2 { if iar.CompletedSynchronously then + // return true + // else + // return! Async.AwaitWaitHandle(iar.AsyncWaitHandle, ?millisecondsTimeout=millisecondsTimeout) } + + + ///// Bind the result of a result cell, calling the appropriate continuation. + //static member BindResult (result: AsyncResult<'T>) : Async2<'T> = + // MakeAsync (fun ctxt -> + // (match result with + // | Ok v -> ctxt.cont v + // | Error exn -> ctxt.econt exn + // | Canceled exn -> ctxt.ccont exn) ) + + ///// Await and use the result of a result cell. The resulting async doesn't support cancellation + ///// or timeout directly, rather the underlying computation must fill the result if cancellation + ///// or timeout occurs. + //static member AwaitAndBindResult_NoDirectCancelOrTimeout(resultCell: ResultCell>) : Async2<'T> = + // async2 { + // let! result = resultCell.AwaitResult_NoDirectCancelOrTimeout + // return! Async.BindResult result + // } + + ///// Await the result of a result cell belonging to a child computation. The resulting async supports timeout and if + ///// it happens the child computation will be cancelled. The resulting async doesn't support cancellation + ///// directly, rather the underlying computation must fill the result if cancellation occurs. + //static member AwaitAndBindChildResult(innerCTS: CancellationTokenSource, resultCell: ResultCell>, millisecondsTimeout) : Async2<'T> = + // match millisecondsTimeout with + // | None | Some -1 -> + // resultCell |> Async.AwaitAndBindResult_NoDirectCancelOrTimeout + + // | Some 0 -> + // async2 { if resultCell.ResultAvailable then + // let res = resultCell.GrabResult() + // return res.Commit() + // else + // return raise (System.TimeoutException()) } + // | _ -> + // async2 { try + // if resultCell.ResultAvailable then + // let res = resultCell.GrabResult() + // return res.Commit() + // else + // let! ok = Async.AwaitWaitHandle (resultCell.GetWaitHandle(), ?millisecondsTimeout=millisecondsTimeout) + // if ok then + // let res = resultCell.GrabResult() + // return res.Commit() + // else // timed out + // // issue cancellation signal + // innerCTS.Cancel() + // // wait for computation to quiesce + // let! _ = Async.AwaitWaitHandle (resultCell.GetWaitHandle()) + // return raise (System.TimeoutException()) + // finally + // resultCell.Close() } + + + //static member FromBeginEnd(beginAction, endAction, ?cancelAction): Async2<'T> = + // async2 { let! cancellationToken = cancellationTokenAsync + // let resultCell = new ResultCell<_>() + + // let once = Once() + + // let registration: CancellationTokenRegistration = + + // let onCancel () = + // // Call the cancellation routine + // match cancelAction with + // | None -> + // // Register the result. This may race with a successful result, but + // // ResultCell allows a race and throws away whichever comes last. + // once.Do(fun () -> + // let canceledResult = Canceled (OperationCanceledException cancellationToken) + // resultCell.RegisterResult(canceledResult, reuseThread=true) |> unfake + // ) + // | Some cancel -> + // // If we get an exception from a cooperative cancellation function + // // we assume the operation has already completed. + // try cancel() with _ -> () + + // cancellationToken.Register(Action(onCancel)) + + // let callback = + // System.AsyncCallback(fun iar -> + // if not iar.CompletedSynchronously then + // // The callback has been activated, so ensure cancellation is not possible + // // beyond this point. + // match cancelAction with + // | Some _ -> + // registration.Dispose() + // | None -> + // once.Do(fun () -> registration.Dispose()) + + // // Run the endAction and collect its result. + // let res = + // try + // Ok(endAction iar) + // with exn -> + // let edi = ExceptionDispatchInfo.RestoreOrCapture exn + // Error edi + + // // Register the result. This may race with a cancellation result, but + // // ResultCell allows a race and throws away whichever comes last. + // resultCell.RegisterResult(res, reuseThread=true) |> unfake) + + // let (iar:IAsyncResult) = beginAction (callback, (null:obj)) + // if iar.CompletedSynchronously then + // registration.Dispose() + // return endAction iar + // else + // // Note: ok to use "NoDirectCancel" here because cancellation has been registered above + // // Note: ok to use "NoDirectTimeout" here because no timeout parameter to this method + // return! Async.AwaitAndBindResult_NoDirectCancelOrTimeout resultCell } + + + //static member FromBeginEnd(arg, beginAction, endAction, ?cancelAction): Async2<'T> = + // Async.FromBeginEnd((fun (iar, state) -> beginAction(arg, iar, state)), endAction, ?cancelAction=cancelAction) + + //static member FromBeginEnd(arg1, arg2, beginAction, endAction, ?cancelAction): Async2<'T> = + // Async.FromBeginEnd((fun (iar, state) -> beginAction(arg1, arg2, iar, state)), endAction, ?cancelAction=cancelAction) + + //static member FromBeginEnd(arg1, arg2, arg3, beginAction, endAction, ?cancelAction): Async2<'T> = + // Async.FromBeginEnd((fun (iar, state) -> beginAction(arg1, arg2, arg3, iar, state)), endAction, ?cancelAction=cancelAction) + + //static member AsBeginEnd<'Arg, 'T> (computation:('Arg -> Async2<'T>)) : + // // The 'Begin' member + // ('Arg * System.AsyncCallback * obj -> System.IAsyncResult) * + // // The 'End' member + // (System.IAsyncResult -> 'T) * + // // The 'Cancel' member + // (System.IAsyncResult -> unit) = + // let beginAction = fun (a1, callback, state) -> AsBeginEndHelpers.beginAction ((computation a1), callback, state) + // beginAction, AsBeginEndHelpers.endAction<'T>, AsBeginEndHelpers.cancelAction<'T> + + //static member AwaitEvent(event:IEvent<'Delegate, 'T>, ?cancelAction) : Async2<'T> = + // async2 { let! cancellationToken = cancellationTokenAsync + // let resultCell = new ResultCell<_>() + // // Set up the handlers to listen to events and cancellation + // let once = Once() + // let rec registration: CancellationTokenRegistration= + // let onCancel () = + // // We've been cancelled. Call the given cancellation routine + // match cancelAction with + // | None -> + // // We've been cancelled without a cancel action. Stop listening to events + // event.RemoveHandler del + // // Register the result. This may race with a successful result, but + // // ResultCell allows a race and throws away whichever comes last. + // once.Do(fun () -> resultCell.RegisterResult(Canceled (OperationCanceledException cancellationToken), reuseThread=true) |> unfake) + // | Some cancel -> + // // If we get an exception from a cooperative cancellation function + // // we assume the operation has already completed. + // try cancel() with _ -> () + // cancellationToken.Register(Action(onCancel)) + + // and del = + // FuncDelegate<'T>.Create<'Delegate>(fun eventArgs -> + // // Stop listening to events + // event.RemoveHandler del + // // The callback has been activated, so ensure cancellation is not possible beyond this point + // once.Do(fun () -> registration.Dispose()) + // let res = Ok eventArgs + // // Register the result. This may race with a cancellation result, but + // // ResultCell allows a race and throws away whichever comes last. + // resultCell.RegisterResult(res, reuseThread=true) |> unfake) + + // // Start listening to events + // event.AddHandler del + + // // Return the async computation that allows us to await the result + // // Note: ok to use "NoDirectCancel" here because cancellation has been registered above + // // Note: ok to use "NoDirectTimeout" here because no timeout parameter to this method + // return! Async.AwaitAndBindResult_NoDirectCancelOrTimeout resultCell } + + //static member StartChild (computation:Async2<'T>, ?millisecondsTimeout) = + // async2 { + // let resultCell = new ResultCell<_>() + // let! cancellationToken = cancellationTokenAsync + // let innerCTS = new CancellationTokenSource() // innerCTS does not require disposal + // let mutable ctsRef = innerCTS + // let reg = cancellationToken.Register( + // (fun () -> + // match ctsRef with + // | null -> () + // | otherwise -> otherwise.Cancel())) + // do QueueAsync + // innerCTS.Token + // // since innerCTS is not ever Disposed, can call reg.Dispose() without a safety Latch + // (fun res -> ctsRef <- null; reg.Dispose(); resultCell.RegisterResult (Ok res, reuseThread=true)) + // (fun edi -> ctsRef <- null; reg.Dispose(); resultCell.RegisterResult (Error edi, reuseThread=true)) + // (fun err -> ctsRef <- null; reg.Dispose(); resultCell.RegisterResult (Canceled err, reuseThread=true)) + // computation + // |> unfake + + // return Async.AwaitAndBindChildResult(innerCTS, resultCell, millisecondsTimeout) } + + //static member SwitchToContext syncContext = + // let t = + // Task.Factory.StartNew( + // (fun () -> ()), // this will use current synchronization context + // CancellationToken.None, + // TaskCreationOptions.None, + // TaskScheduler. .FromCurrentSynchronizationContext()) + // async2 { match syncContext with + // | null -> + // // no synchronization context, just switch to the thread pool + // do! Async.SwitchToThreadPool() + // | syncCtxt -> + // // post the continuation to the synchronization context + // return! CreateSwitchToAsync syncCtxt } + + //static member OnCancel interruption = + // async2 { let! cancellationToken = cancellationTokenAsync + // // latch protects CancellationTokenRegistration.Dispose from being called twice + // let latch = Latch() + // let rec handler () = + // try + // if latch.Enter() then registration.Dispose() + // interruption () + // with _ -> () + // and registration: CancellationTokenRegistration = cancellationToken.Register(Action(handler)) + // return { new System.IDisposable with + // member this.Dispose() = + // // dispose CancellationTokenRegistration only if cancellation was not requested. + // // otherwise - do nothing, disposal will be performed by the handler itself + // if not cancellationToken.IsCancellationRequested then + // if latch.Enter() then registration.Dispose() } } + + //static member TryCancelled (computation: Async2<'T>, compensation) = + // CreateWhenCancelledAsync compensation computation + +//module CommonExtensions = + +// type System.IO.Stream with + +// [] // give the extension member a 'nice', unmangled compiled name, unique within this module +// member stream.AsyncRead(buffer: byte[], ?offset, ?count) = +// let offset = defaultArg offset 0 +// let count = defaultArg count buffer.Length +// Async.FromBeginEnd (buffer, offset, count, stream.BeginRead, stream.EndRead) + +// [] // give the extension member a 'nice', unmangled compiled name, unique within this module +// member stream.AsyncRead count = +// async2 { +// let buffer = Array.zeroCreate count +// let mutable i = 0 +// while i < count do +// let! n = stream.AsyncRead(buffer, i, count - i) +// i <- i + n +// if n = 0 then +// raise(System.IO.EndOfStreamException()) +// return buffer } + +// [] // give the extension member a 'nice', unmangled compiled name, unique within this module +// member stream.AsyncWrite(buffer:byte[], ?offset:int, ?count:int) = +// let offset = defaultArg offset 0 +// let count = defaultArg count buffer.Length +// Async.FromBeginEnd (buffer, offset, count, stream.BeginWrite, stream.EndWrite) + + +//module WebExtensions = + +// type System.Net.WebRequest with +// [] // give the extension member a 'nice', unmangled compiled name, unique within this module +// member req.AsyncGetResponse() : Async2 = + +// let mutable canceled = false // WebException with Status = WebExceptionStatus.RequestCanceled can be raised in other situations except cancellation, use flag to filter out false positives + +// // Use CreateTryWithFilterAsync to allow propagation of exception without losing stack +// Async.FromBeginEnd(beginAction=req.BeginGetResponse, +// endAction = req.EndGetResponse, +// cancelAction = fun() -> canceled <- true; req.Abort()) +// |> CreateTryWithFilterAsync (fun exn -> +// match exn with +// | :? System.Net.WebException as webExn +// when webExn.Status = System.Net.WebExceptionStatus.RequestCanceled && canceled -> + +// Some (Async.BindResult(AsyncResult.Canceled (OperationCanceledException webExn.Message))) +// | _ -> +// None) + +// type System.Net.WebClient with +// member inline private this.Download(event: IEvent<'T, _>, handler: _ -> 'T, start, result) = +// let downloadAsync = +// Async.FromContinuations (fun (cont, econt, ccont) -> +// let userToken = obj() +// let rec delegate' (_: obj) (args: #ComponentModel.AsyncCompletedEventArgs) = +// // ensure we handle the completed event from correct download call +// if userToken = args.UserState then +// event.RemoveHandler handle +// if args.Cancelled then +// ccont (OperationCanceledException()) +// elif isNotNull args.Error then +// econt args.Error +// else +// cont (result args) +// and handle = handler delegate' +// event.AddHandler handle +// start userToken +// ) + +// async2 { +// use! _holder = Async.OnCancel(fun _ -> this.CancelAsync()) +// return! downloadAsync +// } + +// [] // give the extension member a 'nice', unmangled compiled name, unique within this module +// member this.AsyncDownloadString (address:Uri) : Async2 = +// this.Download( +// event = this.DownloadStringCompleted, +// handler = (fun action -> Net.DownloadStringCompletedEventHandler action), +// start = (fun userToken -> this.DownloadStringAsync(address, userToken)), +// result = (fun args -> args.Result) +// ) + +// [] // give the extension member a 'nice', unmangled compiled name, unique within this module +// member this.AsyncDownloadData (address:Uri) : Async2 = +// this.Download( +// event = this.DownloadDataCompleted, +// handler = (fun action -> Net.DownloadDataCompletedEventHandler action), +// start = (fun userToken -> this.DownloadDataAsync(address, userToken)), +// result = (fun args -> args.Result) +// ) + +// [] // give the extension member a 'nice', unmangled compiled name, unique within this module +// member this.AsyncDownloadFile (address:Uri, fileName:string) : Async2 = +// this.Download( +// event = this.DownloadFileCompleted, +// handler = (fun action -> ComponentModel.AsyncCompletedEventHandler action), +// start = (fun userToken -> this.DownloadFileAsync(address, fileName, userToken)), +// result = (fun _ -> ()) +// ) + +module Examples = + + let t1 () = + async2 { + printfn "in t1" + do! Async2.Sleep 100 + printfn "resuming t1" + + return "a" + } + + let testTailcallTiny () = + async2 { + return! t1() + } + let rec testTailcall (n: int) = + async2 { + if n % 100 = 0 then + printfn $"in t1, n = {n}" + if n > 0 then + return! testTailcall(n-1) + //yield () + } + + //let t2 () = + // async2 { + // printfn "in t2" + // yield "d" + // printfn "in t2 b" + // for x in t1 () do + // printfn "t2 - got %A" x + // yield "e" + // let! v = + // task { + // printfn "hey yo" + // do! Task.Delay(200) + // } + // yield "[T1]" + x + // let! v = + // task { + // printfn "hey yo" + // do! Task.Delay(10) + // } + // yield "f" + // } + + let perf1 (x: int) = + async2 { + return 1 + } + + //let perf1_AsyncSeq (x: int) = + // FSharp.Control.AsyncSeqExtensions.asyncSeq { + // yield 1 + // yield 2 + // if x >= 2 then + // yield 3 + // yield 4 + // } + + //let perf2_AsyncSeq () = + // FSharp.Control.AsyncSeqExtensions.asyncSeq { + // for i1 in perf1_AsyncSeq 3 do + // for i2 in perf1_AsyncSeq 3 do + // for i3 in perf1_AsyncSeq 3 do + // for i4 in perf1_AsyncSeq 3 do + // for i5 in perf1_AsyncSeq 3 do + // yield! perf1_AsyncSeq i5 + // } + + let dumpAsync2 (t: Async2<_>) = + printfn "-----" + let e = t.StartImmediate(CancellationToken()) + let res = e.Task.Result + printfn "result: %A" res + + //dumpAsync2 (t1()) + dumpAsync2 (testTailcallTiny()) + ////dumpAsync2 (t2()) + + //printfn "t1() = %A" (Async2.toArray (t1())) + //printfn "testTailcallTiny() = %A" (Async2.toArray (testTailcallTiny())) + //dumpAsync2 (testTailcall(100000)) + //printfn "t2() = %A" (Async2.toArray (t2())) + + //printfn "perf2() = %A" (Async2.toArray (perf2()) |> Array.sum) + diff --git a/tests/benchmarks/TaskPerf/async2.fsi b/tests/benchmarks/TaskPerf/async2.fsi new file mode 100644 index 00000000000..9398b1223c2 --- /dev/null +++ b/tests/benchmarks/TaskPerf/async2.fsi @@ -0,0 +1,255 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace rec FSharp.Control.Async2 + +open System +open System.Threading +open System.Threading.Tasks +open FSharp.Core.CompilerServices +open System.Runtime.CompilerServices + +[] +type Async2StateMachineData<'T> = + new: unit -> Async2StateMachineData<'T> + [] + val mutable cancellationToken: CancellationToken + [] + val mutable result: 'T + [] + val mutable builder: AsyncTaskMethodBuilder<'T> + [] + val mutable taken: bool + //// For tailcalls using 'return!' + //[] + //val mutable tailcallTarget: IAsync2Invocation<'T> + +type Async2Code<'TOverall, 'T> = ResumableCode, 'T> +and Async2StateMachine<'T> = ResumableStateMachine> +and Async2ResumptionFunc<'T> = ResumptionFunc> +and Async2ResumptionDynamicInfo<'T> = ResumptionDynamicInfo> + +type IAsync2Invokable<'T> = + abstract StartImmediate: CancellationToken -> IAsync2Invocation<'T> + +type IAsync2Invocation<'T> = + inherit IAsyncStateMachine + //abstract TailcallTarget: IAsync2Invocation<'T> + abstract CancellationToken: CancellationToken + abstract Task: Task<'T> + +[] +type Async2<'T> = + interface IAsync2Invokable<'T> + interface IAsync2Invocation<'T> + interface IAsyncStateMachine + member inline StartImmediate: ct: CancellationToken -> IAsync2Invocation<'T> + +[] +type Async2<'Machine, 'T when 'Machine :> IAsyncStateMachine and 'Machine :> IResumableStateMachine>> = + new : unit -> Async2<'Machine, 'T> + inherit Async2<'T> + [] + val mutable Machine: 'Machine + interface IAsyncStateMachine + interface IAsync2Invokable<'T> + interface IAsync2Invocation<'T> + +[] +type Async2 = + + static member RunSynchronously: computation:Async2<'T> * ?timeout: int * ?cancellationToken:CancellationToken-> 'T + + static member Start: computation:Async2 * ?cancellationToken:CancellationToken -> unit + + static member StartAsTask: computation:Async2<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T> +(* + static member StartChildAsTask: computation:Async2<'T> * ?taskCreationOptions:TaskCreationOptions -> Async2> +*) + + static member Catch: computation:Async2<'T> -> Async2> + + (* + static member TryCancelled: computation:Async2<'T> * compensation:(OperationCanceledException -> unit) -> Async2<'T> + + static member OnCancel: interruption: (unit -> unit) -> Async2 + *) + + static member CancellationToken: Async2 + + static member CancelDefaultToken: unit -> unit + + static member DefaultCancellationToken: CancellationToken + + //---------- Parallelism +(* + static member StartChild: computation:Async2<'T> * ?millisecondsTimeout: int -> Async2> + + static member Parallel: computations:seq> -> Async2<'T[]> + + static member Parallel: computations:seq> * ?maxDegreeOfParallelism: int -> Async2<'T[]> + + static member Sequential: computations:seq> -> Async2<'T[]> + + static member Choice: computations:seq> -> Async2<'T option> +*) + static member SwitchToNewThread: unit -> Async2 + + static member SwitchToThreadPool: unit -> Async2 + +(* + static member SwitchToContext: syncContext:System.Threading.SynchronizationContext -> Async2 + + static member FromContinuations: callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async2<'T> + + static member AwaitEvent: event:IEvent<'Del,'T> * ?cancelAction: (unit -> unit) -> Async2<'T> when 'Del: delegate<'T,unit> and 'Del :> System.Delegate + + static member AwaitWaitHandle: waitHandle: WaitHandle * ?millisecondsTimeout:int -> Async2 + + static member AwaitIAsyncResult: iar: System.IAsyncResult * ?millisecondsTimeout:int -> Async2 +*) + static member AwaitTask: task: Task<'T> -> Async2<'T> + + static member AwaitTask: task: Task -> Async2 + + static member Sleep: millisecondsDueTime:int -> Async2 + + static member Ignore: computation: Async2<'T> -> Async2 +(* + static member StartWithContinuations: + computation:Async2<'T> * + continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * + ?cancellationToken:CancellationToken-> unit +*) + static member StartImmediate: + computation:Async2 * ?cancellationToken:CancellationToken-> unit + + static member StartImmediateAsTask: + computation:Async2<'T> * ?cancellationToken:CancellationToken-> Task<'T> + +(* +type Async2Return + +[] +type Async2Activation<'T> = + + member IsCancellationRequested: bool + + member OnSuccess: 'T -> Async2Return + + member OnExceptionRaised: unit -> unit + + member OnCancellation: unit -> Async2Return + +[] +module Async2Primitives = + + val MakeAsync: body:(Async2Activation<'T> -> Async2Return) -> Async2<'T> + + val Invoke: computation: Async2<'T> -> ctxt:Async2Activation<'T> -> Async2Return + + val CallThenInvoke: ctxt:Async2Activation<'T> -> result1:'U -> part2:('U -> Async2<'T>) -> Async2Return + + val Bind: ctxt:Async2Activation<'T> -> part1:Async2<'U> -> part2:('U -> Async2<'T>) -> Async2Return + + val TryFinally: ctxt:Async2Activation<'T> -> computation: Async2<'T> -> finallyFunction: (unit -> unit) -> Async2Return + + val TryWith: ctxt:Async2Activation<'T> -> computation: Async2<'T> -> catchFunction: (Exception -> Async2<'T> option) -> Async2Return + +*) + +[] +type Async2Builder = + + member inline Run: code : Async2Code<'T, 'T> -> Async2<'T> + + [] + member inline Zero: unit -> Async2Code<'TOverall, unit> + + member inline Combine: task1: Async2Code<'TOverall, unit> * task2: Async2Code<'TOverall, 'T> -> Async2Code<'TOverall, 'T> + + member inline While: [] condition: (unit -> bool) * body: Async2Code<'TOverall, unit> -> Async2Code<'TOverall, unit> + + member inline Return: v: 'T -> Async2Code<'T, 'T> + + member inline ReturnFrom: task: Task<'T> -> Async2Code<'T, 'T> + + member inline ReturnFrom: computation: Async<'T> -> Async2Code<'T, 'T> + + member inline ReturnFrom: other: Async2<'T> -> Async2Code<'T, 'T> + + member inline Delay: f: (unit -> Async2Code<'TOverall, 'T>) -> Async2Code<'TOverall, 'T> + + member inline Using: resource: ('TResource :> IAsyncDisposable) * body: ('TResource -> Async2Code<'TOverall, 'T>) -> Async2Code<'TOverall, 'T> + + member inline TryFinally: body: Async2Code<'TOverall, 'T> * compensation: (unit -> unit) -> Async2Code<'TOverall, 'T> + + member inline TryWith: body: Async2Code<'TOverall, 'T> * catch: (exn -> Async2Code<'TOverall, 'T>) -> Async2Code<'TOverall, 'T> + + member inline Bind: task: Task<'TResult1> * continuation: ('TResult1 -> Async2Code<'TOverall, 'T>) -> Async2Code<'TOverall, 'T> + + member inline Bind: computation: Async<'TResult1> * continuation: ('TResult1 -> Async2Code<'TOverall, 'T>) -> Async2Code<'TOverall, 'T> + + member inline Bind: computation: Async2<'TResult1> * continuation: ('TResult1 -> Async2Code<'TOverall, 'T>) -> Async2Code<'TOverall, 'T> + + +[] +module Async2 = + type Async2Builder with + member inline ReturnFrom< ^TaskLike, ^Awaiter, ^T + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> ^T)> + : task: ^TaskLike -> Async2Code< ^T, ^T> + + member inline Bind< ^TaskLike, ^TResult1, 'TResult2, ^Awaiter , 'TOverall + when ^TaskLike: (member GetAwaiter: unit -> ^Awaiter) + and ^Awaiter :> ICriticalNotifyCompletion + and ^Awaiter: (member get_IsCompleted: unit -> bool) + and ^Awaiter: (member GetResult: unit -> ^TResult1)> + : task: ^TaskLike * continuation: (^TResult1 -> Async2Code<'TOverall, 'TResult2>) -> Async2Code<'TOverall, 'TResult2> + + member inline Using: resource: ('TResource :> IDisposable) * body: ('TResource -> Async2Code<'TOverall, 'T>) -> Async2Code<'TOverall, 'T> + + member inline For: sequence: seq<'TElement> * body: ('TElement -> Async2Code<'TOverall, unit>) -> Async2Code<'TOverall, unit> + + val async2: Async2Builder +//[] +///// A module of extension members providing asynchronous operations for some basic CLI types related to concurrency and I/O. +///// +///// Async Programming +//module CommonExtensions = + +// type System.IO.Stream with + +// /// Returns an asynchronous computation that will read from the stream into the given buffer. +// /// The buffer to read into. +// /// An optional offset as a number of bytes in the stream. +// /// An optional number of bytes to read from the stream. +// /// +// /// An asynchronous computation that will read from the stream into the given buffer. +// /// Thrown when the sum of offset and count is longer than +// /// the buffer length. +// /// Thrown when offset or count is negative. +// member AsyncRead: buffer:byte[] * ?offset:int * ?count:int -> Async2 + +// /// Returns an asynchronous computation that will read the given number of bytes from the stream. +// /// +// /// The number of bytes to read. +// /// +// /// An asynchronous computation that returns the read byte[] when run. +// member AsyncRead: count:int -> Async2 + +// /// Returns an asynchronous computation that will write the given bytes to the stream. +// /// +// /// The buffer to write from. +// /// An optional offset as a number of bytes in the stream. +// /// An optional number of bytes to write to the stream. +// /// +// /// An asynchronous computation that will write the given bytes to the stream. +// /// Thrown when the sum of offset and count is longer than +// /// the buffer length. +// /// Thrown when offset or count is negative. +// member AsyncWrite: buffer:byte[] * ?offset:int * ?count:int -> Async2 + + diff --git a/tests/benchmarks/TaskPerf/coroutine.fs b/tests/benchmarks/TaskPerf/coroutine.fs new file mode 100644 index 00000000000..04c4defdbfc --- /dev/null +++ b/tests/benchmarks/TaskPerf/coroutine.fs @@ -0,0 +1,279 @@ + + +// This is a sample and test showing how to use resumable code to implement +// coroutines with tailcall support +// +// A coroutine is a value of type Coroutine normally constructed using this form: +// +// coroutine { +// printfn "in t1" +// yield () +// printfn "hey" +// } +// +// We also support `yield!` and tailcalls using the (non-standard) syntax of `return!`/ReturnFrom + +module Tests.Coroutines + +open System +open System.Runtime.CompilerServices +open FSharp.Core.CompilerServices +open FSharp.Core.CompilerServices.StateMachineHelpers +open FSharp.Core.LanguagePrimitives.IntrinsicOperators +open FSharp.Collections + +let verbose = false + +/// Helpers to do zero-allocation call to interface methods on structs +[] +module internal Helpers = + let inline MoveNext(x: byref<'T> when 'T :> IAsyncStateMachine) = x.MoveNext() + let inline SetStateMachine(x: byref<'T> when 'T :> IAsyncStateMachine, state) = x.SetStateMachine(state) + let inline GetResumptionPoint(x: byref<'T> when 'T :> IResumableStateMachine<'Data>) = x.ResumptionPoint + +/// This is the type of coroutines +[] +type Coroutine() = + + /// Checks if the coroutine is completed + abstract IsCompleted: bool + + /// Executes the coroutine until the next 'yield' + abstract MoveNext: unit -> unit + + /// Gets the tailcall target if the coroutine has executed a `return!` + abstract TailcallTarget: Coroutine option + +/// This is the implementation of Coroutine with respect to a particular struct state machine type. +and [] + Coroutine<'Machine when 'Machine : struct + and 'Machine :> IAsyncStateMachine + and 'Machine :> ICoroutineStateMachine>() = + inherit Coroutine() + + // The state machine struct + [] + val mutable Machine: 'Machine + + override cr.IsCompleted = + match cr.TailcallTarget with + | None -> + GetResumptionPoint(&cr.Machine) = -1 + | Some tg -> + tg.IsCompleted + + override cr.TailcallTarget = + CoroutineStateMachineData.GetHijackTarget(&cr.Machine) + + override cr.MoveNext() = + match cr.TailcallTarget with + | None -> //if verbose then printfn $"[{cr.Id}] move" + MoveNext(&cr.Machine) + | Some tg -> + match tg.TailcallTarget with + | None -> tg.MoveNext() + | Some tg2 -> + // Cut out chains of tailcalls + CoroutineStateMachineData.SetHijackTarget(&cr.Machine, tg2) + tg2.MoveNext() +/// This extra data stored in ResumableStateMachine (and it's templated copies using __stateMachine) +/// It only contains one field, the hijack target for tailcalls. +and [] + CoroutineStateMachineData = + + /// This is used for tailcalls using 'return!' + [] + val mutable TailcallTarget: Coroutine option + + static member GetHijackTarget(x: byref<'Machine> when 'Machine :> IResumableStateMachine) = + x.Data.TailcallTarget + + static member SetHijackTarget(x: byref<'Machine>, tg: Coroutine) : unit when 'Machine :> IResumableStateMachine = + let mutable newData = CoroutineStateMachineData() + newData.TailcallTarget <- Some tg + x.Data <- newData + +/// These are standard definitions filling in the 'Data' parameter of each +and ICoroutineStateMachine = IResumableStateMachine +and CoroutineStateMachine = ResumableStateMachine +and CoroutineResumptionFunc = ResumptionFunc +and CoroutineResumptionDynamicInfo = ResumptionDynamicInfo +and CoroutineCode = ResumableCode + + +/// The builder for tailcalls, defined using resumable code combinators +type CoroutineBuilder() = + + member inline _.Delay(f : unit -> CoroutineCode) : CoroutineCode = ResumableCode.Delay(f) + + /// Create the state machine and outer execution logic + member inline _.Run(code : CoroutineCode) : Coroutine = + if __useResumableCode then + __stateMachine + + // IAsyncStateMachine.MoveNext + (MoveNextMethodImpl<_>(fun sm -> + //-- RESUMABLE CODE START + __resumeAt sm.ResumptionPoint + let __stack_code_fin = code.Invoke(&sm) + if __stack_code_fin then + sm.ResumptionPoint <- -1 // indicates complete + else + // Goto request + match sm.Data.TailcallTarget with + | Some tg -> tg.MoveNext() // recurse + | None -> () + //-- RESUMABLE CODE END + )) + + // IAsyncStateMachine.SetStateMachine + (SetStateMachineMethodImpl<_>(fun sm state -> SetStateMachine(&sm, state))) + + // Box the coroutine. In this example we don't start execution of the coroutine. + (AfterCode<_,_>(fun sm -> + let mutable cr = Coroutine() + cr.Machine <- sm + cr :> Coroutine)) + else + // The dynamic implementation + let initialResumptionFunc = CoroutineResumptionFunc(fun sm -> code.Invoke(&sm)) + let resumptionInfo = + { new CoroutineResumptionDynamicInfo(initialResumptionFunc) with + member info.MoveNext(sm) = + if info.ResumptionFunc.Invoke(&sm) then + sm.ResumptionPoint <- -1 + member info.SetStateMachine(sm, state) = () + } + let mutable cr = Coroutine() + cr.Machine.ResumptionDynamicInfo <- resumptionInfo + cr :> Coroutine + + /// Used to represent no-ops like the implicit empty "else" branch of an "if" expression. + [] + member inline _.Zero() : CoroutineCode = ResumableCode.Zero() + + /// Chains together a step with its following step. + /// Note that this requires that the first step has no result. + /// This prevents constructs like `task { return 1; return 2; }`. + member inline _.Combine(code1: CoroutineCode, code2: CoroutineCode) : CoroutineCode = + ResumableCode.Combine(code1, code2) + + /// Builds a step that executes the body while the condition predicate is true. + member inline _.While ([] condition : unit -> bool, body : CoroutineCode) : CoroutineCode = + ResumableCode.While(condition, body) + + /// Wraps a step in a try/with. This catches exceptions both in the evaluation of the function + /// to retrieve the step, and in the continuation of the step (if any). + member inline _.TryWith (body: CoroutineCode, catch: exn -> CoroutineCode) : CoroutineCode = + ResumableCode.TryWith(body, catch) + + /// Wraps a step in a try/finally. This catches exceptions both in the evaluation of the function + /// to retrieve the step, and in the continuation of the step (if any). + member inline _.TryFinally (body: CoroutineCode, [] compensation : unit -> unit) : CoroutineCode = + ResumableCode.TryFinally(body, ResumableCode<_,_>(fun _ -> compensation(); true)) + + member inline _.Using (resource : 'Resource, body : 'Resource -> CoroutineCode) : CoroutineCode when 'Resource :> IDisposable = + ResumableCode.Using(resource, body) + + member inline _.For (sequence : seq<'T>, body : 'T -> CoroutineCode) : CoroutineCode = + ResumableCode.For(sequence, body) + + member inline _.Yield (_dummy: unit) : CoroutineCode = + ResumableCode.Yield() + + // The implementation of `yield!` + member inline _.YieldFrom (other: Coroutine) : CoroutineCode = + ResumableCode.While((fun () -> not other.IsCompleted), CoroutineCode(fun sm -> + other.MoveNext() + let __stack_other_fin = other.IsCompleted + if not __stack_other_fin then + // This will yield with __stack_yield_fin = false + // This will resume with __stack_yield_fin = true + let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm) + __stack_yield_fin + else + true)) + + // The implementation of `return!`, non-standard for tailcalls + member inline _.ReturnFrom (other: Coroutine) : CoroutineCode = + ResumableCode<_,_>(fun sm -> + sm.Data.TailcallTarget <- Some other + // For tailcalls we return 'false' and re-run from the entry (trampoline) + false + // We could do this immediately with future cut-out, though this will stack-dive on sync code. + // We could also trampoline less frequently via a counter + // b.YieldFrom(other).Invoke(&sm) + ) + +[] +module CoroutineBuilder = + + let coroutine = CoroutineBuilder() + + +module Examples = + + let t1 () = + coroutine { + printfn "in t1" + yield () + printfn "hey ho" + yield () + yield! + coroutine{ + printfn "hey yo" + yield () + printfn "hey go" + } + } + + let testTailcallTiny () = + coroutine { + return! t1() + } + let rec testTailcall (n: int) = + coroutine { + if n % 100 = 0 then printfn $"in t1, n = {n}" + yield () + if n > 0 then + return! testTailcall(n-1) + } + + + let t2 () = + coroutine { + printfn "in t2" + yield () + printfn "in t2 b" + yield! t1() + //for x in t1 () do + // printfn "t2 - got %A" x + // yield () + // yield! + // coroutine { + // printfn "hey yo" + // } + // yield "[T1]" + x + yield! + coroutine { + printfn "hey yo" + //do! Task.Delay(10) + } + yield () + } + + + let dumpCoroutine (t: Coroutine) = + printfn "-----" + while ( //if verbose then printfn $"[{t.Id}] calling t.MoveNext, will resume at {t.ResumptionPoint}"; + t.MoveNext() + not t.IsCompleted) do + () // printfn "yield" + + dumpCoroutine (t1()) + dumpCoroutine (testTailcallTiny()) + dumpCoroutine (testTailcall(1000000)) + dumpCoroutine (t2()) + + + diff --git a/tests/benchmarks/TaskPerf/coroutineBasic.fs b/tests/benchmarks/TaskPerf/coroutineBasic.fs new file mode 100644 index 00000000000..8f8d707b6de --- /dev/null +++ b/tests/benchmarks/TaskPerf/coroutineBasic.fs @@ -0,0 +1,169 @@ +// This is a sample and test showing how to use resumable code to implement coroutines +// +// A coroutine is a value of type Coroutine normally constructed using this form: +// +// coroutine { +// printfn "in t1" +// yield () +// printfn "hey" +// } + +module rec Tests.CoroutinesBasic + +open System +open System.Runtime.CompilerServices +open FSharp.Core.CompilerServices +open FSharp.Core.CompilerServices.StateMachineHelpers + +/// This is the type of coroutines +[] +type Coroutine() = + + /// Checks if the coroutine is completed + abstract IsCompleted: bool + + /// Executes the coroutine until the next 'yield' + abstract MoveNext: unit -> unit + +/// Helpers to do zero-allocation call to interface methods on structs +[] +module internal Helpers = + let inline MoveNext(x: byref<'T> when 'T :> IAsyncStateMachine) = x.MoveNext() + let inline GetResumptionPoint(x: byref<'T> when 'T :> IResumableStateMachine<'Data>) = x.ResumptionPoint + let inline SetData(x: byref<'T> when 'T :> IResumableStateMachine<'Data>, data) = x.Data <- data + +/// This is the implementation of Coroutine with respect to a particular struct state machine type. +[] +type Coroutine<'Machine when 'Machine : struct + and 'Machine :> IAsyncStateMachine + and 'Machine :> ICoroutineStateMachine>() = + inherit Coroutine() + + // The state machine struct + [] + val mutable Machine: 'Machine + + override cr.IsCompleted = + GetResumptionPoint(&cr.Machine) = -1 + + override cr.MoveNext() = + MoveNext(&cr.Machine) + +/// This extra data stored in ResumableStateMachine (and it's templated copies using __stateMachine) +/// In this example there is just an ID +[] +type CoroutineStateMachineData(id: int) = + member _.Id = id + +let nextId = + let mutable n = 0 + fun () -> n <- n + 1; n + +/// These are standard definitions filling in the 'Data' parameter of each +type ICoroutineStateMachine = IResumableStateMachine +type CoroutineStateMachine = ResumableStateMachine +type CoroutineResumptionFunc = ResumptionFunc +type CoroutineResumptionDynamicInfo = ResumptionDynamicInfo +type CoroutineCode = ResumableCode + +type CoroutineBuilder() = + + member inline _.Delay(f : unit -> CoroutineCode) : CoroutineCode = ResumableCode.Delay(f) + + /// Used to represent no-ops like the implicit empty "else" branch of an "if" expression. + [] + member inline _.Zero() : CoroutineCode = ResumableCode.Zero() + + // The implementation of `e1; e2` + member inline _.Combine(code1: CoroutineCode, code2: CoroutineCode) : CoroutineCode = + ResumableCode.Combine(code1, code2) + + // The implementation of `while` + member inline _.While ([] condition : unit -> bool, body : CoroutineCode) : CoroutineCode = + ResumableCode.While(condition, body) + + // The implementation of `try/with` + member inline _.TryWith (body: CoroutineCode, catch: exn -> CoroutineCode) : CoroutineCode = + ResumableCode.TryWith(body, catch) + + // The implementation of `try/finally` + member inline _.TryFinally (body: CoroutineCode, [] compensation : unit -> unit) : CoroutineCode = + ResumableCode.TryFinally(body, ResumableCode<_,_>(fun _ -> compensation(); true)) + + // The implementation of `use` + member inline _.Using (resource : 'Resource, body : 'Resource -> CoroutineCode) : CoroutineCode when 'Resource :> IDisposable = + ResumableCode.Using(resource, body) + + // The implementation of `for` + member inline _.For (sequence : seq<'T>, body : 'T -> CoroutineCode) : CoroutineCode = + ResumableCode.For(sequence, body) + + // The implementation of `yield` + member inline _.Yield (_dummy: unit) : CoroutineCode = + ResumableCode.Yield() + + // The implementation of `yield!` + member inline _.YieldFrom (other: Coroutine) : CoroutineCode = + ResumableCode.While((fun () -> not other.IsCompleted), CoroutineCode(fun sm -> + other.MoveNext() + let __stack_other_fin = other.IsCompleted + if not __stack_other_fin then + ResumableCode.Yield().Invoke(&sm) + else + true)) + + /// Create the state machine and outer execution logic + member inline _.Run(code : CoroutineCode) : Coroutine = + if __useResumableCode then + __stateMachine + + // IAsyncStateMachine.MoveNext + (MoveNextMethodImpl<_>(fun sm -> + __resumeAt sm.ResumptionPoint + let __stack_code_fin = code.Invoke(&sm) + if __stack_code_fin then + sm.ResumptionPoint <- -1 // indicates complete + )) + + // IAsyncStateMachine.SetStateMachine + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + + // Box the coroutine. In this example we don't start execution of the coroutine. + (AfterCode<_,_>(fun sm -> + let mutable cr = Coroutine() + SetData(&cr.Machine, CoroutineStateMachineData(nextId())) + cr.Machine <- sm + cr :> Coroutine)) + else + // The dynamic implementation + let initialResumptionFunc = CoroutineResumptionFunc(fun sm -> code.Invoke(&sm)) + let resumptionInfo = + { new CoroutineResumptionDynamicInfo(initialResumptionFunc) with + member info.MoveNext(sm) = + if info.ResumptionFunc.Invoke(&sm) then + sm.ResumptionPoint <- -1 + member info.SetStateMachine(sm, state) = () + } + let mutable cr = Coroutine() + cr.Machine.ResumptionDynamicInfo <- resumptionInfo + cr :> Coroutine + +[] +module CoroutineBuilder = + + let coroutine = CoroutineBuilder() + +module Examples = + let t1 () = + coroutine { + printfn "in t1" + yield () + printfn "hey ho" + yield () + } + let dumpCoroutine (t: Coroutine) = + printfn "-----" + while ( t.MoveNext() + not t.IsCompleted) do + printfn "yield" + diff --git a/tests/benchmarks/TaskPerf/empty.fs b/tests/benchmarks/TaskPerf/empty.fs new file mode 100644 index 00000000000..41ce540367b --- /dev/null +++ b/tests/benchmarks/TaskPerf/empty.fs @@ -0,0 +1,5 @@ + +module Tests.Empty + + +let _ = printfn "hello" \ No newline at end of file diff --git a/tests/benchmarks/TaskPerf/list.fs b/tests/benchmarks/TaskPerf/list.fs new file mode 100644 index 00000000000..14240aac764 --- /dev/null +++ b/tests/benchmarks/TaskPerf/list.fs @@ -0,0 +1,195 @@ + +module Tests.ListBuilders + +#if FSHARP_CORE_HAS_LIST_COLLECTOR +open System +open System.Collections.Generic +open FSharp.Core.CompilerServices + +#nowarn "57" + +[] +module UsingInlinedCodeAndCollector = + [] + type ListBuilderCollector<'T> = + [] + val mutable Collector : ListCollector<'T> + + member sm.Yield (value: 'T) = sm.Collector.Yield(value) + + member sm.ToList() = sm.Collector.ToList() + + type ListBuilderCode<'T> = delegate of byref> -> unit + + type ListBuilderViaCollector() = + + member inline _.Delay([] f: unit -> ListBuilderCode<'T>) : ListBuilderCode<'T> = + ListBuilderCode<_>(fun sm -> (f()).Invoke &sm) + + member inline _.Zero() : ListBuilderCode<'T> = + ListBuilderCode<_>(fun _sm -> ()) + + member inline _.Combine([] part1: ListBuilderCode<'T>, [] part2: ListBuilderCode<'T>) : ListBuilderCode<'T> = + ListBuilderCode<_>(fun sm -> + part1.Invoke &sm + part2.Invoke &sm) + + member inline _.While([] condition : unit -> bool, [] body : ListBuilderCode<'T>) : ListBuilderCode<'T> = + ListBuilderCode<_>(fun sm -> + while condition() do + body.Invoke &sm) + + member inline _.TryWith([] body: ListBuilderCode<'T>, [] handler: exn -> ListBuilderCode<'T>) : ListBuilderCode<'T> = + ListBuilderCode<_>(fun sm -> + try + body.Invoke &sm + with exn -> + (handler exn).Invoke &sm) + + member inline _.TryFinally([] body: ListBuilderCode<'T>, compensation : unit -> unit) : ListBuilderCode<'T> = + ListBuilderCode<_>(fun sm -> + try + body.Invoke &sm + with _ -> + compensation() + reraise() + + compensation()) + + member inline b.Using(disp : #IDisposable, [] body: #IDisposable -> ListBuilderCode<'T>) : ListBuilderCode<'T> = + // A using statement is just a try/finally with the finally block disposing if non-null. + b.TryFinally( + (fun sm -> (body disp).Invoke &sm), + (fun () -> if not (isNull (box disp)) then disp.Dispose())) + + member inline b.For(sequence: seq<'TElement>, [] body: 'TElement -> ListBuilderCode<'T>) : ListBuilderCode<'T> = + b.Using (sequence.GetEnumerator(), + (fun e -> b.While((fun () -> e.MoveNext()), (fun sm -> (body e.Current).Invoke &sm)))) + + member inline _.Yield (v: 'T) : ListBuilderCode<'T> = + ListBuilderCode<_>(fun sm -> + sm.Yield v) + + member inline b.YieldFrom (source: IEnumerable<'T>) : ListBuilderCode<'T> = + b.For(source, (fun value -> b.Yield(value))) + + member inline _.Run([] code: ListBuilderCode<'T>) : 'T list = + let mutable sm = ListBuilderCollector<'T>() + code.Invoke &sm + sm.ToList() + + let listc = ListBuilderViaCollector() + +module Examples = + let t1C () = + listc { + printfn "in t1" + yield "a" + let x = "d" + yield "b" + yield "c" + x + } + + let t2C () = + listc { + printfn "in t2" + yield "d" + for x in t1C () do + printfn "t2 - got %A" x + yield "e" + yield "[T1]" + x + yield "f" + } + + let tinyVariableSizeNew () = + for i in 1 .. 1000000 do + listc { + if i % 3 = 0 then + yield "b" + } |> List.length |> ignore + + let tinyVariableSizeBuiltin () = + for i in 1 .. 1000000 do + [ + if i % 3 = 0 then + yield "b" + ] |> List.length |> ignore + + let variableSizeNew () = + for i in 1 .. 1000000 do + listc { + yield "a" + yield "b" + yield "b" + yield "b" + yield "b" + if i % 3 = 0 then + yield "b" + yield "b" + yield "b" + yield "b" + yield "c" + } |> List.length |> ignore + + let variableSizeBuiltin () = + for i in 1 .. 1000000 do + [ + yield "a" + yield "b" + yield "b" + yield "b" + yield "b" + if i % 3 = 0 then + yield "b" + yield "b" + yield "b" + yield "b" + yield "c" + ] |> List.length |> ignore + + let fixedSizeC () = + for i in 1 .. 1000000 do + listc { + "a" + "b" + "b" + "b" + "b" + "b" + "b" + "b" + "b" + "c" + } |> List.length |> ignore + + let fixedSizeBase () = + for i in 1 .. 1000000 do + [ + "a" + "b" + "b" + "b" + "b" + "b" + "b" + "b" + "b" + "c" + ] |> List.length |> ignore + + let perf s f = + let t = System.Diagnostics.Stopwatch() + t.Start() + f() + t.Stop() + printfn "PERF: %s : %d" s t.ElapsedMilliseconds + + perf "tinyVariableSizeBuiltin" tinyVariableSizeBuiltin + perf "tinyVariableSizeNew " tinyVariableSizeNew + + perf "variableSizeBuiltin" variableSizeBuiltin + perf "variableSizeNew" variableSizeNew + + perf "fixedSizeBase" fixedSizeBase + perf "fixedSizeC" fixedSizeC +#endif \ No newline at end of file diff --git a/tests/benchmarks/TaskPerf/option.fs b/tests/benchmarks/TaskPerf/option.fs new file mode 100644 index 00000000000..20003378273 --- /dev/null +++ b/tests/benchmarks/TaskPerf/option.fs @@ -0,0 +1,310 @@ + +module Tests.OptionBuilders + +open System + +type OptionCode<'T> = unit -> 'T voption + +type OptionBuilderUsingInlineIfLambdaBase() = + + member inline _.Delay([] f : unit -> OptionCode<'T>) : OptionCode<'T> = + (fun () -> (f())()) + // Note, not "f()()" - the F# compiler optimzier likes arguments to match lamdas in order to preserve + // argument evaluation order, so for "(f())()" the optimizer reduces one lambda then another, while "f()()" doesn't + + member inline _.Combine([] task1: OptionCode, [] task2: OptionCode<'T>) : OptionCode<'T> = + (fun () -> + match task1() with + | ValueNone -> ValueNone + | ValueSome() -> task2()) + + member inline _.Bind(res1: 'T1 option, [] task2: ('T1 -> OptionCode<'T>)) : OptionCode<'T> = + (fun () -> + match res1 with + | None -> ValueNone + | Some v -> (task2 v)()) + + member inline _.Bind(res1: 'T1 voption, [] task2: ('T1 -> OptionCode<'T>)) : OptionCode<'T> = + (fun () -> + match res1 with + | ValueNone -> ValueNone + | ValueSome v -> (task2 v)()) + + member inline _.While([] condition : unit -> bool, [] body : OptionCode) : OptionCode = + (fun () -> + let mutable proceed = true + while proceed && condition() do + match body() with + | ValueNone -> proceed <- false + | ValueSome () -> () + ValueSome(())) + + member inline _.TryWith([] body : OptionCode<'T>, [] catch : exn -> OptionCode<'T>) : OptionCode<'T> = + (fun () -> + try + body() + with exn -> + (catch exn)()) + + member inline _.TryFinally([] body: OptionCode<'T>, [] compensation : unit -> unit) : OptionCode<'T> = + (fun () -> + let res = + try + body() + with _ -> + compensation() + reraise() + + compensation() + res) + + member inline this.Using(disp: #IDisposable, [] body: #IDisposable -> OptionCode<'T>) : OptionCode<'T> = + // A using statement is just a try/finally with the finally block disposing if non-null. + this.TryFinally( + (fun () -> (body disp)()), + (fun () -> if not (isNull (box disp)) then disp.Dispose())) + + member inline this.For(sequence : seq<'TElement>, [] body : 'TElement -> OptionCode) : OptionCode = + this.Using (sequence.GetEnumerator(), + (fun e -> this.While((fun () -> e.MoveNext()), (fun () -> (body e.Current)())))) + + member inline _.Return (value: 'T) : OptionCode<'T> = + (fun () -> + ValueSome value) + + member inline this.ReturnFrom (source: option<'T>) : OptionCode<'T> = + (fun () -> + match source with Some x -> ValueOption.Some x | None -> ValueOption.None) + + member inline this.ReturnFrom (source: voption<'T>) : OptionCode<'T> = + (fun () -> source) + +type OptionBuilderUsingInlineIfLambda() = + inherit OptionBuilderUsingInlineIfLambdaBase() + + member inline _.Run([] code : OptionCode<'T>) : 'T option = + match code () with + | ValueNone -> None + | ValueSome v -> Some v + +type ValueOptionBuilderUsingInlineIfLambda() = + inherit OptionBuilderUsingInlineIfLambdaBase() + + member inline _.Run([] code : OptionCode<'T>) : 'T voption = + code() + +let optionNew = OptionBuilderUsingInlineIfLambda() +let voptionNew = ValueOptionBuilderUsingInlineIfLambda() + + +type SlowOptionBuilder() = + member inline _.Zero() = None + + member inline _.Return(x: 'T) = Some x + + member inline _.ReturnFrom(m: 'T option) = m + + member inline _.Bind(m: 'T option, f) = Option.bind f m + + member inline _.Delay(f: unit -> _) = f + + member inline _.Run(f) = f() + + member this.TryWith(delayedExpr, handler) = + try this.Run(delayedExpr) + with exn -> handler exn + + member this.TryFinally(delayedExpr, compensation) = + try this.Run(delayedExpr) + finally compensation() + + member this.Using(resource:#IDisposable, body) = + this.TryFinally(this.Delay(fun ()->body resource), fun () -> match box resource with null -> () | _ -> resource.Dispose()) + +let optionOld = SlowOptionBuilder() + +type SlowValueOptionBuilder() = + member inline _.Zero() = ValueNone + + member inline _.Return(x: 'T) = ValueSome x + + member inline _.ReturnFrom(m: 'T voption) = m + + member inline _.Bind(m: 'T voption, f) = ValueOption.bind f m + + member inline _.Delay(f: unit -> _) = f + + member inline _.Run(f) = f() + + member inline this.TryWith(delayedExpr, handler) = + try this.Run(delayedExpr) + with exn -> handler exn + + member inline this.TryFinally(delayedExpr, compensation) = + try this.Run(delayedExpr) + finally compensation() + + member inline this.Using(resource:#IDisposable, body) = + this.TryFinally(this.Delay(fun ()->body resource), fun () -> match box resource with null -> () | _ -> resource.Dispose()) + +let voptionOld = SlowValueOptionBuilder() + +module Examples = + + + let multiStepOldBuilder () = + let mutable res = 0 + for i in 1 .. 1000000 do + let v = + optionOld { + try + let! x1 = (if i % 5 <> 2 then Some i else None) + let! x2 = (if i % 3 <> 1 then Some i else None) + let! x3 = (if i % 3 <> 1 then Some i else None) + let! x4 = (if i % 3 <> 1 then Some i else None) + res <- res + 1 + return x1 + x2 + x3 + x4 + with e -> + return failwith "unexpected" + } + v |> ignore + res + + let multiStepOldBuilderV () = + let mutable res = 0 + for i in 1 .. 1000000 do + let v = + voptionOld { + try + let! x1 = (if i % 5 <> 2 then ValueSome i else ValueNone) + let! x2 = (if i % 3 <> 1 then ValueSome i else ValueNone) + let! x3 = (if i % 3 <> 1 then ValueSome i else ValueNone) + let! x4 = (if i % 3 <> 1 then ValueSome i else ValueNone) + res <- res + 1 + return x1 + x2 + x3 + x4 + with e -> + return failwith "unexpected" + } + v |> ignore + res + + let multiStepNoBuilder () = + let mutable res = 0 + for i in 1 .. 1000000 do + let v = + try + match (if i % 5 <> 2 then Some i else None) with + | None -> None + | Some x1 -> + match (if i % 3 <> 1 then Some i else None) with + | None -> None + | Some x2 -> + match (if i % 3 <> 1 then Some i else None) with + | None -> None + | Some x3 -> + match (if i % 3 <> 1 then Some i else None) with + | None -> None + | Some x4 -> + res <- res + 1 + Some (x1 + x2 + x3 + x4) + with e -> + failwith "unexpected" + v |> ignore + res + + let multiStepNoBuilderV () = + let mutable res = 0 + for i in 1 .. 1000000 do + let v = + try + match (if i % 5 <> 2 then ValueSome i else ValueNone) with + | ValueNone -> ValueNone + | ValueSome x1 -> + match (if i % 3 <> 1 then ValueSome i else ValueNone) with + | ValueNone -> ValueNone + | ValueSome x2 -> + match (if i % 3 <> 1 then ValueSome i else ValueNone) with + | ValueNone -> ValueNone + | ValueSome x3 -> + match (if i % 3 <> 1 then ValueSome i else ValueNone) with + | ValueNone -> ValueNone + | ValueSome x4 -> + res <- res + 1 + ValueSome (x1 + x2 + x3 + x4) + with e -> + failwith "unexpected" + v |> ignore + res + + let multiStepNewBuilder () = + let mutable res = 0 + for i in 1 .. 1000000 do + let v = + optionNew { + try + let! x1 = (if i % 5 <> 2 then Some i else None) + let! x2 = (if i % 3 <> 1 then Some i else None) + let! x3 = (if i % 3 <> 1 then Some i else None) + let! x4 = (if i % 3 <> 1 then Some i else None) + res <- res + 1 + return x1 + x2 + x3 + x4 + with e -> + return failwith "unexpected" + } + v |> ignore + res + + + let multiStepNewBuilderV () = + let mutable res = 0 + for i in 1 .. 1000000 do + let v = + voptionNew { + try + let! x1 = (if i % 5 <> 2 then ValueSome i else ValueNone) + let! x2 = (if i % 3 <> 1 then ValueSome i else ValueNone) + let! x3 = (if i % 3 <> 1 then ValueSome i else ValueNone) + let! x4 = (if i % 3 <> 1 then ValueSome i else ValueNone) + res <- res + 1 + return x1 + x2 + x3 + x4 + with e -> + return failwith "unexpected" + } + v |> ignore + res + + // let perf s f = + // let t = System.Diagnostics.Stopwatch() + // t.Start() + // for i in 1 .. 100 do + // f() |> ignore + // t.Stop() + // printfn "PERF: %s : %d" s t.ElapsedMilliseconds + + // printfn "check %d = %d = %d"(multiStepStateMachineBuilder()) (multiStepNoBuilder()) (multiStepOldBuilder()) + + // perf "perf (state mechine option)" multiStepStateMachineBuilder + // perf "perf (no builder option)" multiStepNoBuilder + // perf "perf (slow builder option)" multiStepOldBuilder + + // printfn "check %d = %d = %d" (multiStepStateMachineBuilderV()) (multiStepNoBuilder()) (multiStepOldBuilder()) + // perf "perf (state mechine voption)" multiStepStateMachineBuilderV + // perf "perf (no builder voption)" multiStepNoBuilderV + // perf "perf (slow builder voption)" multiStepOldBuilderV + +module A = + + let multiStepNewBuilder (i) = + let mutable res = 0 + optionNew { + try + let! x1 = (if i % 5 <> 2 then Some i else None) + let! x2 = (if i % 3 <> 1 then Some i else None) + let! x3 = (if i % 3 <> 1 then Some i else None) + let! x4 = (if i % 3 <> 1 then Some i else None) + res <- res + 1 + return x1 + x2 + x3 + x4 + with e -> + return failwith "unexpected" + } + diff --git a/tests/benchmarks/TaskPerf/option2.fs b/tests/benchmarks/TaskPerf/option2.fs new file mode 100644 index 00000000000..7d911b68890 --- /dev/null +++ b/tests/benchmarks/TaskPerf/option2.fs @@ -0,0 +1,25 @@ + +module Tests.OptionBuilderUsingInlineIfLambda + +open System + + + // let perf s f = + // let t = System.Diagnostics.Stopwatch() + // t.Start() + // for i in 1 .. 100 do + // f() |> ignore + // t.Stop() + // printfn "PERF: %s : %d" s t.ElapsedMilliseconds + + // printfn "check %d = %d = %d"(multiStepInlineIfLambdaBuilder()) (multiStepNoBuilder()) (multiStepOldBuilder()) + + // perf "perf (state mechine option)" multiStepInlineIfLambdaBuilder + // perf "perf (no builder option)" multiStepNoBuilder + // perf "perf (slow builder option)" multiStepOldBuilder + + // printfn "check %d = %d = %d" (multiStepInlineIfLambdaBuilderV()) (multiStepNoBuilder()) (multiStepOldBuilder()) + // perf "perf (state mechine voption)" multiStepInlineIfLambdaBuilderV + // perf "perf (no builder voption)" multiStepNoBuilderV + // perf "perf (slow builder voption)" multiStepOldBuilderV + diff --git a/tests/benchmarks/TaskPerf/seq2.fs b/tests/benchmarks/TaskPerf/seq2.fs new file mode 100644 index 00000000000..5df130c6eae --- /dev/null +++ b/tests/benchmarks/TaskPerf/seq2.fs @@ -0,0 +1,262 @@ + +module Tests.Seq2 + +#nowarn "42" +open System +open System.Collections +open System.Collections.Generic +open System.Runtime.CompilerServices +open FSharp.Core.CompilerServices +open FSharp.Core.CompilerServices.StateMachineHelpers + +[] +type SeqStateMachine<'T>() = + let disposalStack = ResizeArray<(unit -> unit)>() + + /// Proceed to the next state or raise an exception. Returns true if completed + abstract Step : unit -> bool + + member val Current : 'T voption = ValueNone with get, set + + member val ResumptionPoint: int = 0 with get, set + + member val ResumptionFunc: (SeqStateMachine<'T> -> bool) = Unchecked.defaultof<_> with get, set + + interface IEnumerable with + member this.GetEnumerator() = + // TODO: make new object if needed + (this :> IEnumerator) + + interface IEnumerable<'T> with + member this.GetEnumerator() = + // TODO: make new object if needed + (this :> IEnumerator<'T>) + + interface IDisposable with + member __.Dispose() = + let mutable exn = None + for d in Seq.rev disposalStack do + try + d() + with e -> + exn <- Some e // keep the last exception - TODO - check this + match exn with + | None -> () + | Some e -> raise e + + interface IEnumerator with + + member __.Reset() = failwith "no reset supported" + member sm.Current = box sm.Current + member sm.MoveNext() = sm.Step() + + interface IEnumerator<'T> with + member sm.Current = match sm.Current with ValueNone -> failwith "no value available yet" | ValueSome x -> x + + member __.PushDispose (f: unit -> unit) = disposalStack.Add(f) + + member __.PopDispose () = disposalStack.RemoveAt(disposalStack.Count - 1) + + [] + member sm.Start() = (sm :> IEnumerable<'T>) + +type SeqCode<'T> = SeqStateMachine<'T> -> bool + +type SeqBuilder() = + + [] + member inline __.Delay(__expand_f : unit -> SeqCode<'T>) : SeqCode<'T> = (fun sm -> __expand_f () sm) + + [] + member inline __.Run(__expand_code : SeqCode<'T>) : IEnumerable<'T> = + if __useResumableCode then + (__resumableStateMachine + { new SeqStateMachine<'T>() with + member sm.Step () = + __resumeAt sm.ResumptionPoint + __expand_code sm }).Start() + else + let sm = + { new SeqStateMachine<'T>() with + member sm.Step () = + sm.ResumptionFunc sm } + sm.ResumptionFunc <- __expand_code + sm.Start() + + [] + member inline __.Zero() : SeqCode<'T> = + (fun _sm -> true) + + [] + member inline __.Combine(__expand_task1: SeqCode<'T>, __expand_task2: SeqCode<'T>) : SeqCode<'T> = + (fun sm -> + if __useResumableCode then + let __stack_step = __expand_task1 sm + if __stack_step then + __expand_task2 sm + else + false + else + let completed = __expand_task1 sm + if completed then + __expand_task2 sm + else + // If state machines are not supported, then we must adjust the resumption to also run __expand_task2 on completion + let rec resume rf = + (fun (sm: SeqStateMachine<_>) -> + let completed = rf sm + if completed then + __expand_task2 sm + else + sm.ResumptionFunc <- resume sm.ResumptionFunc + false) + + sm.ResumptionFunc <- resume sm.ResumptionFunc + false) + + [] + member inline __.While(__expand_condition : unit -> bool, __expand_body : SeqCode<'T>) : SeqCode<'T> = + (fun sm -> + if __useResumableCode then + let mutable __stack_completed = false + while __stack_completed && __expand_condition() do + // NOTE: The body of the 'while' may contain await points, resuming may branch directly into the while loop + let __stack_step = __expand_body sm + // If we make it to the assignment we prove we've made a step + __stack_completed <- __stack_step + __stack_completed + else + let rec repeat sm = + if __expand_condition() then + let step = __expand_body sm + if step then + repeat sm + else + //Console.WriteLine("[{0}] rebinding ResumptionFunc for While", sm.MethodBuilder.Task.Id) + sm.ResumptionFunc <- resume sm.ResumptionFunc + false + else + true + and resume mf sm = + //Console.WriteLine("[{0}] resume WhileLoop body", sm.MethodBuilder.Task.Id) + let step = mf sm + if step then + repeat sm + else + //Console.WriteLine("[{0}] rebinding ResumptionFunc for While", sm.MethodBuilder.Task.Id) + sm.ResumptionFunc <- resume sm.ResumptionFunc + false + + repeat sm) + + [] + member inline __.TryWith(__expand_body : SeqCode<'T>, __expand_catch : exn -> SeqCode<'T>) : SeqCode<'T> = + (fun sm -> + if __useResumableCode then + let mutable __stack_completed = false + let mutable __stack_caught = false + let mutable __stack_savedExn = Unchecked.defaultof<_> + try + // The try block may contain await points. + let __stack_step = __expand_body sm + // If we make it to the assignment we prove we've made a step + __stack_completed <- __stack_step + with exn -> + __stack_caught <- true + __stack_savedExn <- exn + + if __stack_caught then + // Place the catch code outside the catch block + __expand_catch __stack_savedExn sm + else + __stack_completed + else + failwith "tbd") + + [] + member inline __.TryFinally(__expand_body: SeqCode<'T>, compensation : unit -> unit) : SeqCode<'T> = + (fun sm -> + let mutable completed = false + sm.PushDispose compensation + try + let __stack_step = __expand_body sm + // If we make it to the assignment we prove we've made a step without an exception + completed <- __stack_step + with _ -> + sm.PopDispose() + compensation() + reraise() + + if completed then + sm.PopDispose() + compensation() + completed) + + [] + member inline this.Using(disp : #IDisposable, __expand_body : #IDisposable -> SeqCode<'T>) = + // A using statement is just a try/finally with the finally block disposing if non-null. + this.TryFinally( + (fun sm -> __expand_body disp sm), + (fun () -> if not (isNull (box disp)) then disp.Dispose())) + + [] + member inline this.For(sequence : seq<'TElement>, __expand_body : 'TElement -> SeqCode<'T>) : SeqCode<'T> = + // A for loop is just a using statement on the sequence's enumerator... + this.Using (sequence.GetEnumerator(), + // ... and its body is a while loop that advances the enumerator and runs the body on each element. + (fun e -> this.While((fun () -> e.MoveNext()), (fun sm -> __expand_body e.Current sm)))) + + [] + member inline __.Yield (v: 'T) : SeqCode<'T> = + (fun sm -> + if __useResumableCode then + match __resumableEntry() with + | Some contID -> + sm.ResumptionPoint <- contID + sm.Current <- ValueSome v + false + | None -> + sm.Current <- ValueNone + true + else + let cont (sm: SeqStateMachine<'T>) = + sm.Current <- ValueNone + true + sm.ResumptionFunc <- cont + sm.Current <- ValueSome v + false) + + [] + member inline this.YieldFrom (source: IEnumerable<'T>) : SeqCode<'T> = + this.For(source, (fun v -> this.Yield v)) + +let seq2 = SeqBuilder() + +module Examples = + + let t1 () = + seq2 { + printfn "in t1" + yield "a" + let x = 1 + yield "b" + yield "c" + } + + let t2 () = + seq2 { + printfn "in t2" + yield "d" + for x in t1 () do + printfn "t2 - got %A" x + yield "e" + yield "[T1]" + x + yield "f" + } + + let dumpSeq (t: IEnumerable<_>) = + let e = t.GetEnumerator() + while e.MoveNext() do + printfn "yield %A" e.Current + dumpSeq (t1()) + dumpSeq (t2()) diff --git a/tests/benchmarks/TaskPerf/sync.fs b/tests/benchmarks/TaskPerf/sync.fs new file mode 100644 index 00000000000..9a4ccb5b72f --- /dev/null +++ b/tests/benchmarks/TaskPerf/sync.fs @@ -0,0 +1,88 @@ + +module Tests.SyncBuilder + +open System + +type SyncCode<'T> = unit -> 'T + +type SyncBuilder() = + + member inline _.Delay([] f: unit -> SyncCode<'T>) : SyncCode<'T> = + (fun () -> (f())()) + + member inline _.Run([] code : SyncCode<'T>) : 'T = + code() + +#if PREVIEW + [] +#endif + member inline _.Zero() : SyncCode< unit> = + (fun () -> ()) + + member inline _.Return (x: 'T) : SyncCode<'T> = + (fun () -> x) + + member inline _.Combine([] code1: SyncCode, [] code2: SyncCode<'T>) : SyncCode<'T> = + (fun () -> + code1() + code2()) + + member inline _.While([] condition: unit -> bool, [] body: SyncCode) : SyncCode = + (fun () -> + while condition() do + body()) + + member inline _.TryWith([] body: SyncCode<'T>, [] catch: exn -> 'T) : SyncCode<'T> = + (fun () -> + try + body() + with exn -> + catch exn) + + member inline _.TryFinally([] body: SyncCode<'T>, compensation: unit -> unit) : SyncCode<'T> = + (fun () -> + let __stack_step = + try + body() + with _ -> + compensation() + reraise() + compensation() + __stack_step) + + member inline this.Using(disp : #IDisposable, [] body: #IDisposable -> SyncCode<'T>) : SyncCode<'T> = + this.TryFinally( + (fun () -> (body disp)()), + (fun () -> if not (isNull (box disp)) then disp.Dispose())) + + member inline this.For(sequence : seq<'T>, [] body : 'T -> SyncCode) : SyncCode = + this.Using (sequence.GetEnumerator(), + (fun e -> this.While((fun () -> e.MoveNext()), (fun () -> (body e.Current)())))) + + member inline _.ReturnFrom (value: 'T) : SyncCode<'T> = + (fun () -> + value) + + member inline _.Bind (v: 'TResult1, [] continuation: 'TResult1 -> SyncCode<'TResult2>) : SyncCode<'TResult2> = + (fun () -> + (continuation v)()) + +let sync = SyncBuilder() + +module Examples = + + let t1 y = + sync { + let x = 4 + 5 + y + return x + } + + let t2 y = + sync { + printfn "in t2" + let! x = t1 y + return x + y + } + + + //printfn "t2 6 = %d" (t2 6) diff --git a/tests/benchmarks/TaskPerf/taskSeq.fs b/tests/benchmarks/TaskPerf/taskSeq.fs new file mode 100644 index 00000000000..c87c79f37db --- /dev/null +++ b/tests/benchmarks/TaskPerf/taskSeq.fs @@ -0,0 +1,599 @@ + +module Tests.TaskSeq + +open System.Runtime.CompilerServices +open System.Threading.Tasks.Sources + +#nowarn "42" +open System +open System.Collections.Generic +open System.Threading +open System.Threading.Tasks +open FSharp.Core.CompilerServices +open FSharp.Core.CompilerServices.StateMachineHelpers + +let verbose = false + +let inline MoveNext(x: byref<'T> when 'T :> IAsyncStateMachine) = x.MoveNext() + +type taskSeq<'T> = IAsyncEnumerable<'T> + +type IPriority1 = interface end +type IPriority2 = interface end + +[] +type TaskSeqStateMachineData<'T>() = + [] + val mutable cancellationToken : CancellationToken + [] + val mutable disposalStack : ResizeArray<(unit -> Task)> + [] + val mutable awaiter : ICriticalNotifyCompletion + [] + val mutable promiseOfValueOrEnd: ManualResetValueTaskSourceCore + [] + val mutable builder : AsyncIteratorMethodBuilder + [] + val mutable taken : bool + [] + val mutable current : ValueOption<'T> + [] + val mutable boxed: TaskSeq<'T> + // For tailcalls using 'return!' + [] + val mutable tailcallTarget: TaskSeq<'T> option + + member data.PushDispose (f: unit -> Task) = + match data.disposalStack with + | null -> data.disposalStack <- ResizeArray() + | _ -> () + data.disposalStack.Add(f) + + member data.PopDispose () = + match data.disposalStack with + | null -> () + | _ -> + data.disposalStack.RemoveAt(data.disposalStack.Count - 1) + +and [] + TaskSeq<'T>() = + abstract TailcallTarget: TaskSeq<'T> option + abstract MoveNextAsyncResult: unit -> ValueTask + + // F# requires that we implement interfaces even on an abstract class + interface IAsyncEnumerator<'T> with + member _.Current = failwith "abstract" + member _.MoveNextAsync() = failwith "abstract" + interface IAsyncDisposable with + member _.DisposeAsync() = failwith "abstract" + interface IAsyncEnumerable<'T> with + member _.GetAsyncEnumerator(ct) = failwith "abstract" + interface IAsyncStateMachine with + member _.MoveNext() = failwith "abstract" + member _.SetStateMachine(_state) = failwith "abstract" + interface IValueTaskSource with + member _.GetResult(_token: int16) = failwith "abstract" + member _.GetStatus(_token: int16) = failwith "abstract" + member _.OnCompleted(_continuation, _state, _token, _flags) = failwith "abstract" + interface IValueTaskSource with + member _.GetStatus(_token: int16) = failwith "abstract" + member _.GetResult(_token: int16) = failwith "abstract" + member _.OnCompleted(_continuation, _state, _token, _flags) = failwith "abstract" + +and [] + TaskSeq<'Machine, 'T when 'Machine :> IAsyncStateMachine and 'Machine :> IResumableStateMachine>>() = + inherit TaskSeq<'T>() + let initialThreadId = Environment.CurrentManagedThreadId + + [] + val mutable Machine : 'Machine + + member internal ts.hijack() = + let res = ts.Machine.Data.tailcallTarget + match res with + | Some tg -> + match tg.TailcallTarget with + | None -> + res + | (Some tg2 as res2) -> + // Cut out chains of tailcalls + ts.Machine.Data.tailcallTarget <- Some tg2 + res2 + | None -> + res + + // Note: Not entirely clear if this is needed, everything still compiles without it + interface IValueTaskSource with + member ts.GetResult(token: int16) = + match ts.hijack() with + | Some tg -> (tg :> IValueTaskSource).GetResult(token) + | None -> ts.Machine.Data.promiseOfValueOrEnd.GetResult(token) |> ignore + member ts.GetStatus(token: int16) = + match ts.hijack() with + | Some tg -> (tg :> IValueTaskSource).GetStatus(token) + | None -> ts.Machine.Data.promiseOfValueOrEnd.GetStatus(token) + member ts.OnCompleted(continuation, state, token, flags) = + match ts.hijack() with + | Some tg -> (tg :> IValueTaskSource).OnCompleted(continuation, state, token, flags) + | None -> ts.Machine.Data.promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags) + + // Needed for MoveNextAsync to return a ValueTask + interface IValueTaskSource with + member ts.GetStatus(token: int16) = + match ts.hijack() with + | Some tg -> (tg :> IValueTaskSource).GetStatus(token) + | None -> ts.Machine.Data.promiseOfValueOrEnd.GetStatus(token) + member ts.GetResult(token: int16) = + match ts.hijack() with + | Some tg -> (tg :> IValueTaskSource).GetResult(token) + | None -> ts.Machine.Data.promiseOfValueOrEnd.GetResult(token) + member ts.OnCompleted(continuation, state, token, flags) = + match ts.hijack() with + | Some tg -> (tg :> IValueTaskSource).OnCompleted(continuation, state, token, flags) + | None -> ts.Machine.Data.promiseOfValueOrEnd.OnCompleted(continuation, state, token, flags) + + interface IAsyncStateMachine with + member ts.MoveNext() = + match ts.hijack() with + | Some tg -> (tg :> IAsyncStateMachine).MoveNext() + | None -> MoveNext(&ts.Machine) + + member _.SetStateMachine(_state) = () // not needed for reference type + + interface IAsyncEnumerable<'T> with + member ts.GetAsyncEnumerator(ct) = + let data = ts.Machine.Data + if (not data.taken && initialThreadId = Environment.CurrentManagedThreadId) then + data.taken <- true + data.cancellationToken <- ct + data.builder <- AsyncIteratorMethodBuilder.Create() + (ts :> IAsyncEnumerator<_>) + else + if verbose then printfn "GetAsyncEnumerator, cloning..." + let clone = ts.MemberwiseClone() :?> TaskSeq<'Machine, 'T> + data.taken <- true + clone.Machine.Data.cancellationToken <- ct + (clone :> System.Collections.Generic.IAsyncEnumerator<'T>) + + interface IAsyncDisposable with + member ts.DisposeAsync() = + match ts.hijack() with + | Some tg -> (tg :> IAsyncDisposable).DisposeAsync() + | None -> + if verbose then printfn "DisposeAsync..." + task { + match ts.Machine.Data.disposalStack with + | null -> () + | _ -> + let mutable exn = None + for d in Seq.rev ts.Machine.Data.disposalStack do + try + do! d() + with e -> + if exn.IsNone then + exn <- Some e + match exn with + | None -> () + | Some e -> raise e + } + |> ValueTask + + interface System.Collections.Generic.IAsyncEnumerator<'T> with + member ts.Current = + match ts.hijack() with + | Some tg -> (tg :> IAsyncEnumerator<'T>).Current + | None -> + match ts.Machine.Data.current with + | ValueSome x -> x + | ValueNone -> failwith "no current value" + + member ts.MoveNextAsync() = + match ts.hijack() with + | Some tg -> (tg :> IAsyncEnumerator<'T>).MoveNextAsync() + | None -> + if verbose then printfn "MoveNextAsync..." + if ts.Machine.ResumptionPoint = -1 then // can't use as IAsyncEnumerator before IAsyncEnumerable + ValueTask() + else + let data = ts.Machine.Data + data.promiseOfValueOrEnd.Reset() + let mutable ts = ts + data.builder.MoveNext(&ts) + + // If the move did a hijack then get the result from the final one + match ts.hijack() with + | Some tg -> tg.MoveNextAsyncResult() + | None -> ts.MoveNextAsyncResult() + + override ts.MoveNextAsyncResult() = + let data = ts.Machine.Data + let version = data.promiseOfValueOrEnd.Version + let status = data.promiseOfValueOrEnd.GetStatus(version) + if status = ValueTaskSourceStatus.Succeeded then + let result = data.promiseOfValueOrEnd.GetResult(version) + ValueTask(result) + else + if verbose then printfn "MoveNextAsync pending/faulted/cancelled..." + ValueTask(ts, version) // uses IValueTaskSource<'T> + + override cr.TailcallTarget = + cr.hijack() + +and TaskSeqCode<'T> = ResumableCode, unit> +and TaskSeqStateMachine<'T> = ResumableStateMachine> +and TaskSeqResumptionFunc<'T> = ResumptionFunc> +and TaskSeqResumptionDynamicInfo<'T> = ResumptionDynamicInfo> + +type TaskSeqBuilder() = + + member inline _.Delay(f : unit -> TaskSeqCode<'T>) : TaskSeqCode<'T> = + TaskSeqCode<'T>(fun sm -> f().Invoke(&sm)) + + member inline _.Run(code : TaskSeqCode<'T>) : IAsyncEnumerable<'T> = + if __useResumableCode then + // This is the static implementation. A new struct type is created. + __stateMachine, IAsyncEnumerable<'T>> + // IAsyncStateMachine.MoveNext + (MoveNextMethodImpl<_>(fun sm -> + //-- RESUMABLE CODE START + __resumeAt sm.ResumptionPoint + try + //printfn "at Run.MoveNext start" + //Console.WriteLine("[{0}] resuming by invoking {1}....", sm.MethodBuilder.Task.Id, hashq sm.ResumptionFunc ) + let __stack_code_fin = code.Invoke(&sm) + //printfn $"at Run.MoveNext, __stack_code_fin={__stack_code_fin}" + if __stack_code_fin then + //printfn $"at Run.MoveNext, done" + sm.Data.promiseOfValueOrEnd.SetResult(false) + sm.Data.builder.Complete() + elif sm.Data.current.IsSome then + //printfn $"at Run.MoveNext, yield" + sm.Data.promiseOfValueOrEnd.SetResult(true) + else + // Goto request + match sm.Data.tailcallTarget with + | Some tg -> + //printfn $"at Run.MoveNext, hijack" + let mutable tg = tg + MoveNext(&tg) + | None -> + //printfn $"at Run.MoveNext, await" + let boxed = sm.Data.boxed + sm.Data.awaiter.UnsafeOnCompleted(Action(fun () -> + let mutable boxed = boxed + MoveNext(&boxed))) + + with exn -> + //Console.WriteLine("[{0}] SetException {1}", sm.MethodBuilder.Task.Id, exn) + sm.Data.promiseOfValueOrEnd.SetException(exn) + sm.Data.builder.Complete() + //-- RESUMABLE CODE END + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> + let ts = TaskSeq, 'T>() + ts.Machine <- sm + ts.Machine.Data <- TaskSeqStateMachineData() + ts.Machine.Data.boxed <- ts + ts :> IAsyncEnumerable<'T>)) + else + failwith "no dynamic implementation as yet" + // let initialResumptionFunc = TaskSeqResumptionFunc<'T>(fun sm -> code.Invoke(&sm)) + // let resumptionFuncExecutor = TaskSeqResumptionExecutor<'T>(fun sm f -> + // // TODO: add exception handling? + // if f.Invoke(&sm) then + // sm.ResumptionPoint <- -2) + // let setStateMachine = SetStateMachineMethodImpl<_>(fun sm f -> ()) + // sm.Machine.ResumptionFuncInfo <- (initialResumptionFunc, resumptionFuncExecutor, setStateMachine) + //sm.Start() + + + member inline _.Zero() : TaskSeqCode<'T> = + ResumableCode.Zero() + + member inline _.Combine(task1: TaskSeqCode<'T>, task2: TaskSeqCode<'T>) : TaskSeqCode<'T> = + ResumableCode.Combine(task1, task2) + + member inline _.WhileAsync([] condition : unit -> ValueTask, body : TaskSeqCode<'T>) : TaskSeqCode<'T> = + let mutable condition_res = true + ResumableCode.While((fun () -> condition_res), + ResumableCode<_,_>(fun sm -> + let mutable __stack_condition_fin = true + let __stack_vtask = condition() + if __stack_vtask.IsCompleted then + __stack_condition_fin <- true + condition_res <- __stack_vtask.Result + else + let task = __stack_vtask.AsTask() + let mutable awaiter = task.GetAwaiter() + // This will yield with __stack_fin = false + // This will resume with __stack_fin = true + let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm) + __stack_condition_fin <- __stack_yield_fin + + if __stack_condition_fin then + condition_res <- task.Result + else + //if verbose then printfn "calling AwaitUnsafeOnCompleted" + sm.Data.awaiter <- awaiter + sm.Data.current <- ValueNone + + if __stack_condition_fin then + if condition_res then + body.Invoke(&sm) + else + true + else + false + )) + + member inline b.While([] condition : unit -> bool, body : TaskSeqCode<'T>) : TaskSeqCode<'T> = + b.WhileAsync((fun () -> ValueTask(condition())), body) + + member inline _.TryWith(body : TaskSeqCode<'T>, catch : exn -> TaskSeqCode<'T>) : TaskSeqCode<'T> = + ResumableCode.TryWith(body, catch) + + member inline _.TryFinallyAsync(body: TaskSeqCode<'T>, compensation : unit -> Task) : TaskSeqCode<'T> = + ResumableCode.TryFinallyAsync( + TaskSeqCode<'T>(fun sm -> + sm.Data.PushDispose (fun () -> compensation()) + body.Invoke(&sm)), + ResumableCode<_,_>(fun sm -> + sm.Data.PopDispose(); + let mutable __stack_condition_fin = true + let __stack_vtask = compensation() + if not __stack_vtask.IsCompleted then + let mutable awaiter = __stack_vtask.GetAwaiter() + let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm) + __stack_condition_fin <- __stack_yield_fin + + if not __stack_condition_fin then + sm.Data.awaiter <- awaiter + + __stack_condition_fin)) + + member inline _.TryFinally(body: TaskSeqCode<'T>, compensation : unit -> unit) : TaskSeqCode<'T> = + ResumableCode.TryFinally( + TaskSeqCode<'T>(fun sm -> + sm.Data.PushDispose (fun () -> compensation(); Task.CompletedTask) + body.Invoke(&sm)), + ResumableCode<_,_>(fun sm -> sm.Data.PopDispose(); compensation(); true)) + + member inline this.Using(disp : #IDisposable, body : #IDisposable -> TaskSeqCode<'T>, ?priority: IPriority2) : TaskSeqCode<'T> = + ignore priority + // A using statement is just a try/finally with the finally block disposing if non-null. + this.TryFinally( + (fun sm -> (body disp).Invoke(&sm)), + (fun () -> if not (isNull (box disp)) then disp.Dispose())) + + member inline this.Using(disp : #IAsyncDisposable, body : #IAsyncDisposable -> TaskSeqCode<'T>, ?priority: IPriority1) : TaskSeqCode<'T> = + ignore priority + // A using statement is just a try/finally with the finally block disposing if non-null. + this.TryFinallyAsync( + (fun sm -> (body disp).Invoke(&sm)), + (fun () -> + if not (isNull (box disp)) then + disp.DisposeAsync().AsTask() + else + Task.CompletedTask)) + + member inline this.For(sequence : seq<'TElement>, body : 'TElement -> TaskSeqCode<'T>) : TaskSeqCode<'T> = + // A for loop is just a using statement on the sequence's enumerator... + this.Using (sequence.GetEnumerator(), + // ... and its body is a while loop that advances the enumerator and runs the body on each element. + (fun e -> this.While((fun () -> e.MoveNext()), (fun sm -> (body e.Current).Invoke(&sm))))) + + member inline this.For(source: #IAsyncEnumerable<'TElement>, body : 'TElement -> TaskSeqCode<'T>) : TaskSeqCode<'T> = + TaskSeqCode<'T>(fun sm -> + this.Using(source.GetAsyncEnumerator(sm.Data.cancellationToken), + (fun e -> this.WhileAsync((fun () -> e.MoveNextAsync()), + (fun sm -> (body e.Current).Invoke(&sm))))).Invoke(&sm)) + + member inline _.Yield (v: 'T) : TaskSeqCode<'T> = + TaskSeqCode<'T>(fun sm -> + // This will yield with __stack_fin = false + // This will resume with __stack_fin = true + let __stack_fin = ResumableCode.Yield().Invoke(&sm) + sm.Data.current <- ValueSome v + sm.Data.awaiter <- null + __stack_fin) + + member inline this.YieldFrom (source: IAsyncEnumerable<'T>) : TaskSeqCode<'T> = + this.For(source, (fun v -> this.Yield(v))) + + member inline _.Bind (task: Task<'TResult1>, continuation: ('TResult1 -> TaskSeqCode<'T>)) : TaskSeqCode<'T> = + TaskSeqCode<'T>(fun sm -> + let mutable awaiter = task.GetAwaiter() + let mutable __stack_fin = true + if not awaiter.IsCompleted then + // This will yield with __stack_fin2 = false + // This will resume with __stack_fin2 = true + let __stack_fin2 = ResumableCode.Yield().Invoke(&sm) + __stack_fin <- __stack_fin2 + + if __stack_fin then + let result = awaiter.GetResult() + (continuation result).Invoke(&sm) + else + if verbose then printfn "calling AwaitUnsafeOnCompleted" + sm.Data.awaiter <- awaiter + sm.Data.current <- ValueNone + false) + + // TODO: using return! for tailcalls is wrong. We should use yield! and have F# + // desugar to a different builder method when in tailcall position + // + // Because of this using return! from non-tailcall position e.g. in a try-finally or try-with will + // giv incorrect results (escaping the exception handler - 'close up shop and draw results from somewhere else') + member inline b.ReturnFrom (other: IAsyncEnumerable<'T>) : TaskSeqCode<'T> = + TaskSeqCode<_>(fun sm -> + match other with + | :? TaskSeq<'T> as other -> + sm.Data.tailcallTarget <- Some other + sm.Data.awaiter <- null + sm.Data.current <- ValueNone + // For tailcalls we return 'false' and re-run from the entry (trampoline) + false + | _ -> + b.YieldFrom(other).Invoke(&sm) + ) + +let taskSeq = TaskSeqBuilder() + +module TaskSeq = + let toList (t: taskSeq<'T>) = + [ let e = t.GetAsyncEnumerator(CancellationToken()) + try + while (let vt = e.MoveNextAsync() in if vt.IsCompleted then vt.Result else vt.AsTask().Result) do + yield e.Current + finally + e.DisposeAsync().AsTask().Wait() ] + + let toArray (t: taskSeq<'T>) = + [| let e = t.GetAsyncEnumerator(CancellationToken()) + try + while (let vt = e.MoveNextAsync() in if vt.IsCompleted then vt.Result else vt.AsTask().Result) do + yield e.Current + finally + e.DisposeAsync().AsTask().Wait() |] + + let toArrayAsync (t: taskSeq<'T>) : Task<'T[]> = + task { + let res = ResizeArray<'T>() + let e = t.GetAsyncEnumerator(CancellationToken()) + let mutable go = true + let! step = e.MoveNextAsync() + go <- step + while go do + res.Add e.Current + if verbose then printfn "yield %A" e.Current + let! step = e.MoveNextAsync() + go <- step + return res.ToArray() + } + + let iter f (t: taskSeq<'T>) = + let e = t.GetAsyncEnumerator(CancellationToken()) + try + while (let vt = e.MoveNextAsync() in if vt.IsCompleted then vt.Result else vt.AsTask().Result) do + f e.Current + finally + e.DisposeAsync().AsTask().Wait() + +module Examples = + + let t1 () = + taskSeq { + printfn "in t1" + yield "a" + let x = 1 + let! v = + task { + printfn "hey" + do! Task.Delay(10) + } + yield "b" + let! v = + task { + printfn "hey yo" + do! Task.FromResult(()) + } + yield "c" + let! v = + task { + printfn "and a bottle of rum" + do! Task.Delay(0) + } + yield "d" + } + + let testTailcallTiny () = + taskSeq { + return! t1() + } + let rec testTailcall (n: int) = + taskSeq { + if n % 100 = 0 then printfn $"in t1, n = {n}" + yield n + if n > 0 then + return! testTailcall(n-1) + //yield () + } + + //let t2 () = + // taskSeq { + // printfn "in t2" + // yield "d" + // printfn "in t2 b" + // for x in t1 () do + // printfn "t2 - got %A" x + // yield "e" + // let! v = + // task { + // printfn "hey yo" + // do! Task.Delay(200) + // } + // yield "[T1]" + x + // let! v = + // task { + // printfn "hey yo" + // do! Task.Delay(10) + // } + // yield "f" + // } + + let perf1 (x: int) = + taskSeq { + yield 1 + yield 2 + if x >= 2 then + yield 3 + yield 4 + } + + let perf2 () = + taskSeq { + for i1 in perf1 3 do + for i2 in perf1 3 do + for i3 in perf1 3 do + for i4 in perf1 3 do + for i5 in perf1 3 do + yield! perf1 i5 + } + + //let perf1_AsyncSeq (x: int) = + // FSharp.Control.AsyncSeqExtensions.asyncSeq { + // yield 1 + // yield 2 + // if x >= 2 then + // yield 3 + // yield 4 + // } + + //let perf2_AsyncSeq () = + // FSharp.Control.AsyncSeqExtensions.asyncSeq { + // for i1 in perf1_AsyncSeq 3 do + // for i2 in perf1_AsyncSeq 3 do + // for i3 in perf1_AsyncSeq 3 do + // for i4 in perf1_AsyncSeq 3 do + // for i5 in perf1_AsyncSeq 3 do + // yield! perf1_AsyncSeq i5 + // } + + let dumpTaskSeq (t: IAsyncEnumerable<_>) = + printfn "-----" + let e = t.GetAsyncEnumerator(CancellationToken()) + while (let vt = e.MoveNextAsync() in if vt.IsCompleted then vt.Result else vt.AsTask().Result) do + printfn "yield %A" e.Current + + //dumpTaskSeq (t1()) + //dumpTaskSeq (testTailcallTiny()) + ////dumpTaskSeq (t2()) + + //printfn "t1() = %A" (TaskSeq.toArray (t1())) + //printfn "testTailcallTiny() = %A" (TaskSeq.toArray (testTailcallTiny())) + //dumpTaskSeq (testTailcall(100000)) + //printfn "t2() = %A" (TaskSeq.toArray (t2())) + + printfn "perf2() = %A" (TaskSeq.toArray (perf2()) |> Array.sum) + diff --git a/tests/benchmarks/TaskPerfCSharp/TaskPerfCSharp.cs b/tests/benchmarks/TaskPerfCSharp/TaskPerfCSharp.cs new file mode 100644 index 00000000000..32ea6fcb66c --- /dev/null +++ b/tests/benchmarks/TaskPerfCSharp/TaskPerfCSharp.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; + +#pragma warning disable 1998 + +public static class TaskPerfCSharp +{ + public const int BufferSize = 128; + //public const int ManyIterations = 10000; + + public static async Task ManyWriteFileAsync(int ManyIterations) + { + const string path = "tmp"; + var junk = new byte[BufferSize]; + using (var file = File.Create(path)) + { + for (var i = 1; i <= ManyIterations; i++) + { + await file.WriteAsync(junk, 0, junk.Length); + } + } + File.Delete(path); + } + + public static System.Runtime.CompilerServices.YieldAwaitable AsyncTask() + { + return Task.Yield(); + } + + public static Task SyncTask() + { + return Task.FromResult(100); + } + + public static async Task TenBindsSync_CSharp() + { + var x1 = await SyncTask(); + var x2 = await SyncTask(); + var x3 = await SyncTask(); + var x4 = await SyncTask(); + var x5 = await SyncTask(); + var x6 = await SyncTask(); + var x7 = await SyncTask(); + var x8 = await SyncTask(); + var x9 = await SyncTask(); + var x10 = await SyncTask(); + return x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10; + } + + public static async Task TenBindsAsync_CSharp() + { + await AsyncTask(); + await AsyncTask(); + await AsyncTask(); + await AsyncTask(); + await AsyncTask(); + await AsyncTask(); + await AsyncTask(); + await AsyncTask(); + await AsyncTask(); + await AsyncTask(); + return 100; + } + + public static async Task SingleSyncTask_CSharp() + { + return 1; + } + + public static async Task SingleSyncExceptionTask_CSharp() + { + throw (new System.Exception("fail")); + } + + + public static async IAsyncEnumerable perf1_AsyncEnumerable(int x) + { + yield return 1; + yield return 2; + if (x >= 2) + { + yield return 3; + yield return 4; + } + } + + public static async IAsyncEnumerable perf2_AsyncEnumerable() + { + await foreach (var i1 in perf1_AsyncEnumerable(3)) + { + await foreach (var i2 in perf1_AsyncEnumerable(3)) + { + await foreach (var i3 in perf1_AsyncEnumerable(3)) + { + await foreach (var i4 in perf1_AsyncEnumerable(3)) + { + await foreach (var i5 in perf1_AsyncEnumerable(3)) + { + await foreach (var i6 in perf1_AsyncEnumerable(i5)) + { + yield return i6; + + } + } + + } + + } + + } + + } + } + +#if MAIN + public static void Main() { + var t = SingleSyncExceptionTask_CSharp(); + System.Console.WriteLine("t = {0}", t); + } +#endif +} + diff --git a/tests/benchmarks/TaskPerfCSharp/TaskPerfCSharp.csproj b/tests/benchmarks/TaskPerfCSharp/TaskPerfCSharp.csproj new file mode 100644 index 00000000000..f55b590cb26 --- /dev/null +++ b/tests/benchmarks/TaskPerfCSharp/TaskPerfCSharp.csproj @@ -0,0 +1,14 @@ + + + + netcoreapp3.1 + Library + 8.0 + + + + + + + + diff --git a/tests/benchmarks/TaskPerfPreviousCompiler/TaskPerfPreviousCompiler.fsproj b/tests/benchmarks/TaskPerfPreviousCompiler/TaskPerfPreviousCompiler.fsproj new file mode 100644 index 00000000000..d9446577406 --- /dev/null +++ b/tests/benchmarks/TaskPerfPreviousCompiler/TaskPerfPreviousCompiler.fsproj @@ -0,0 +1,30 @@ + + + + net5.0 + Exe + true + $(OtherFlags) --define:ASYNC_PERF + true + + C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\FSharp + fsc.exe + + + + + + + + + + + + + + + + + + + diff --git a/tests/benchmarks/TaskPerfPreviousCompiler/defs.fs b/tests/benchmarks/TaskPerfPreviousCompiler/defs.fs new file mode 100644 index 00000000000..42cea70022c --- /dev/null +++ b/tests/benchmarks/TaskPerfPreviousCompiler/defs.fs @@ -0,0 +1,14 @@ + +namespace Tests + +open System + +#if !PREVIEW + +[] +[] +type InlineIfLambdaAttribute() = + inherit Attribute() + +#endif + diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/ComputationExpressionOptimizations.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/ComputationExpressionOptimizations.fs new file mode 100644 index 00000000000..9f88f5bf94e --- /dev/null +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/ComputationExpressionOptimizations.fs @@ -0,0 +1,317 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests.CodeGen.EmittedIL + +open FSharp.Test.Utilities +open NUnit.Framework + +open System + +[] +module ComputationExpressionOptimizations = + + [] + // See https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1034-lambda-optimizations.md + // + // This tests a number of code optimizations cooperating together. + // - InlineIfLambda must be applied + // - Computed functions must be reduced. + // + // This is for the "sync { ... }" builder that simply runs code synchronously - no + // one uses this in practice but it's a good baseline test for the elimination and redution of constructs. + // + let ``check reduction of sample builder for synchronous code``() = + CompilerAssert.CompileLibraryAndVerifyIL + """ +module Test + +open System + +type SyncCode<'T> = unit -> 'T + +type SyncBuilder() = + + member inline _.Delay([] f: unit -> SyncCode<'T>) : SyncCode<'T> = + (fun () -> (f())()) + + member inline _.Run([] code : SyncCode<'T>) : 'T = + code() + + [] + member inline _.Zero() : SyncCode< unit> = + (fun () -> ()) + + member inline _.Return (x: 'T) : SyncCode<'T> = + (fun () -> x) + + member inline _.Combine([] code1: SyncCode, [] code2: SyncCode<'T>) : SyncCode<'T> = + (fun () -> + code1() + code2()) + + member inline _.While([] condition: unit -> bool, [] body: SyncCode) : SyncCode = + (fun () -> + while condition() do + body()) + + member inline _.TryWith([] body: SyncCode<'T>, [] catch: exn -> SyncCode<'T>) : SyncCode<'T> = + (fun () -> + try + body() + with exn -> + (catch exn)()) + + member inline _.TryFinally([] body: SyncCode<'T>, compensation: unit -> unit) : SyncCode<'T> = + (fun () -> + let res = + try + body() + with _ -> + compensation() + reraise() + compensation() + res) + + member inline this.Using(disp : #IDisposable, [] body: #IDisposable -> SyncCode<'T>) : SyncCode<'T> = + this.TryFinally( + (fun () -> (body disp)()), + (fun () -> if not (isNull (box disp)) then disp.Dispose())) + + member inline this.For(sequence : seq<'T>, [] body : 'T -> SyncCode) : SyncCode = + this.Using (sequence.GetEnumerator(), + (fun e -> this.While((fun () -> e.MoveNext()), (fun () -> (body e.Current)())))) + + member inline _.ReturnFrom (value: 'T) : SyncCode<'T> = + (fun () -> + value) + + member inline _.Bind (v: 'TResult1, [] continuation: 'TResult1 -> SyncCode<'TResult2>) : SyncCode<'TResult2> = + (fun () -> + (continuation v)()) + +let sync = SyncBuilder() + +module Examples = + + let t1 y = + sync { + let x = 4 + 5 + y + return x + } + + let testFunctionWithBind y = + sync { + printfn "step" + let! x = t1 y + return x + y + } + + let testFunctionWithWhile y = + sync { + printfn "step" + while y < 0 do + let! x = t1 y + printfn $"step {x}" + + return y + y + } + let testFunctionWithTryCatch y = + sync { + try + printfn "step" + let! x = t1 y + return x + y + with _ -> + return 5 + } + let testFunctionWithFinally y = + sync { + try + printfn "step" + let! x = t1 y + return x + y + finally + printfn "step" + } + """ + (fun verifier -> verifier.VerifyIL [ + // Check testFunctionWithBind is flattened + """ +.method public static int32 testFunctionWithBind(int32 y) cil managed +{ + + .maxstack 4 + .locals init (class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_0) + IL_0000: ldstr "step" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_000a: stloc.0 + IL_000b: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0010: ldloc.0 + IL_0011: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0016: pop + IL_0017: ldc.i4.s 9 + IL_0019: ldarg.0 + IL_001a: add + IL_001b: ldarg.0 + IL_001c: add + IL_001d: ret +} + """ + + // Check testFunctionWithWhile is flattened + """ +.method public static int32 testFunctionWithWhile(int32 y) cil managed +{ + + .maxstack 7 + .locals init (class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_0, + int32 V_1) + IL_0000: ldstr "step" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_000a: stloc.0 + IL_000b: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0010: ldloc.0 + IL_0011: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0016: pop + IL_0017: ldarg.0 + IL_0018: ldc.i4.0 + IL_0019: bge.s IL_004d + + IL_001b: ldc.i4.s 9 + IL_001d: ldarg.0 + IL_001e: add + IL_001f: stloc.1 + IL_0020: ldstr "step %P()" + IL_0025: ldc.i4.1 + IL_0026: newarr [runtime]System.Object + IL_002b: dup + IL_002c: ldc.i4.0 + IL_002d: ldloc.1 + IL_002e: box [runtime]System.Int32 + IL_0033: stelem [runtime]System.Object + IL_0038: ldnull + IL_0039: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string, + object[], + class [runtime]System.Type[]) + IL_003e: stloc.0 + IL_003f: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0044: ldloc.0 + IL_0045: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_004a: pop + IL_004b: br.s IL_0017 + + IL_004d: ldarg.0 + IL_004e: ldarg.0 + IL_004f: add + IL_0050: ret +} + """ + + // Check testFunctionWithTryCatch is flattened + """ +.method public static int32 testFunctionWithTryCatch(int32 y) cil managed +{ + + .maxstack 4 + .locals init (int32 V_0, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_1, + class [runtime]System.Exception V_2) + .try + { + IL_0000: ldstr "step" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_000a: stloc.1 + IL_000b: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0010: ldloc.1 + IL_0011: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0016: pop + IL_0017: ldc.i4.s 9 + IL_0019: ldarg.0 + IL_001a: add + IL_001b: ldarg.0 + IL_001c: add + IL_001d: stloc.0 + IL_001e: leave.s IL_002a + + } + catch [runtime]System.Object + { + IL_0020: castclass [runtime]System.Exception + IL_0025: stloc.2 + IL_0026: ldc.i4.5 + IL_0027: stloc.0 + IL_0028: leave.s IL_002a + + } + IL_002a: ldloc.0 + IL_002b: ret +} + """ + // Check testFunctionWithFinally is flattened + """ +.method public static int32 testFunctionWithFinally(int32 y) cil managed +{ + + .maxstack 4 + .locals init (int32 V_0, + int32 V_1, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_2, + class [runtime]System.Exception V_3) + .try + { + IL_0000: ldstr "step" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_000a: stloc.2 + IL_000b: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0010: ldloc.2 + IL_0011: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0016: pop + IL_0017: ldc.i4.s 9 + IL_0019: ldarg.0 + IL_001a: add + IL_001b: ldarg.0 + IL_001c: add + IL_001d: stloc.1 + IL_001e: leave.s IL_0048 + + } + catch [runtime]System.Object + { + IL_0020: castclass [runtime]System.Exception + IL_0025: stloc.3 + IL_0026: ldstr "step" + IL_002b: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0030: stloc.2 + IL_0031: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0036: ldloc.2 + IL_0037: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_003c: pop + IL_003d: rethrow + IL_003f: ldnull + IL_0040: unbox.any [runtime]System.Int32 + IL_0045: stloc.1 + IL_0046: leave.s IL_0048 + + } + IL_0048: ldloc.1 + IL_0049: stloc.0 + IL_004a: ldstr "step" + IL_004f: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0054: stloc.2 + IL_0055: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_005a: ldloc.2 + IL_005b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0060: pop + IL_0061: ldloc.0 + IL_0062: ret +} + """ + ]) + diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/ComputedListExpressions.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/ComputedListExpressions.fs index 5db43f3a5b6..4ba85d0067b 100644 --- a/tests/fsharp/Compiler/CodeGen/EmittedIL/ComputedListExpressions.fs +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/ComputedListExpressions.fs @@ -221,72 +221,70 @@ let ListExpressionSteppingTest5 () = """ (fun verifier -> verifier.VerifyIL [ """ - .method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 - ListExpressionSteppingTest5() cil managed - { - - .maxstack 5 - .locals init (valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1 V_0, - class [runtime]System.Collections.Generic.IEnumerator`1 V_1, - class [runtime]System.Collections.Generic.IEnumerable`1 V_2, - int32 V_3, - class [runtime]System.IDisposable V_4) - IL_0000: ldc.i4.1 - IL_0001: ldc.i4.1 - IL_0002: ldc.i4.4 - IL_0003: call class [runtime]System.Collections.Generic.IEnumerable`1 [FSharp.Core]Microsoft.FSharp.Core.Operators/OperatorIntrinsics::RangeInt32(int32, - int32, - int32) - IL_0008: callvirt instance class [runtime]System.Collections.Generic.IEnumerator`1 class [runtime]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_000d: stloc.1 - .try - { - IL_000e: ldloc.1 - IL_000f: callvirt instance bool [runtime]System.Collections.IEnumerator::MoveNext() - IL_0014: brfalse.s IL_0039 - - IL_0016: ldloc.1 - IL_0017: callvirt instance !0 class [runtime]System.Collections.Generic.IEnumerator`1::get_Current() - IL_001c: stloc.3 - IL_001d: ldstr "hello" - IL_0022: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) - IL_0027: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_002c: pop - IL_002d: ldloca.s V_0 - IL_002f: ldloc.3 - IL_0030: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Add(!0) - IL_0035: nop - IL_0036: nop - IL_0037: br.s IL_000e - - IL_0039: ldnull - IL_003a: stloc.2 - IL_003b: leave.s IL_0056 - - } - finally - { - IL_003d: ldloc.1 - IL_003e: isinst [runtime]System.IDisposable - IL_0043: stloc.s V_4 - IL_0045: ldloc.s V_4 - IL_0047: brfalse.s IL_0053 - - IL_0049: ldloc.s V_4 - IL_004b: callvirt instance void [runtime]System.IDisposable::Dispose() - IL_0050: ldnull - IL_0051: pop - IL_0052: endfinally - IL_0053: ldnull - IL_0054: pop - IL_0055: endfinally - } - IL_0056: ldloc.2 - IL_0057: pop - IL_0058: ldloca.s V_0 - IL_005a: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() - IL_005f: ret - } +.method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 + ListExpressionSteppingTest5() cil managed + { + + .maxstack 5 + .locals init (valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1 V_0, + class [runtime]System.Collections.Generic.IEnumerator`1 V_1, + class [runtime]System.Collections.Generic.IEnumerable`1 V_2, + int32 V_3, + class [runtime]System.IDisposable V_4) + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.1 + IL_0002: ldc.i4.4 + IL_0003: call class [runtime]System.Collections.Generic.IEnumerable`1 [FSharp.Core]Microsoft.FSharp.Core.Operators/OperatorIntrinsics::RangeInt32(int32, + int32, + int32) + IL_0008: callvirt instance class [runtime]System.Collections.Generic.IEnumerator`1 class [runtime]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_000d: stloc.1 + .try + { + IL_000e: ldloc.1 + IL_000f: callvirt instance bool [runtime]System.Collections.IEnumerator::MoveNext() + IL_0014: brfalse.s IL_0039 + + IL_0016: ldloc.1 + IL_0017: callvirt instance !0 class [runtime]System.Collections.Generic.IEnumerator`1::get_Current() + IL_001c: stloc.3 + IL_001d: ldstr "hello" + IL_0022: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0027: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_002c: pop + IL_002d: ldloca.s V_0 + IL_002f: ldloc.3 + IL_0030: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Add(!0) + IL_0035: nop + IL_0036: nop + IL_0037: br.s IL_000e + + IL_0039: ldnull + IL_003a: stloc.2 + IL_003b: leave.s IL_0052 + + } + finally + { + IL_003d: ldloc.1 + IL_003e: isinst [runtime]System.IDisposable + IL_0043: stloc.s V_4 + IL_0045: ldloc.s V_4 + IL_0047: brfalse.s IL_0051 + + IL_0049: ldloc.s V_4 + IL_004b: callvirt instance void [runtime]System.IDisposable::Dispose() + IL_0050: endfinally + IL_0051: endfinally + } + IL_0052: ldloc.2 + IL_0053: pop + IL_0054: ldloca.s V_0 + IL_0056: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() + IL_005b: ret + } + +} """ ]) @@ -311,97 +309,95 @@ let ListExpressionSteppingTest6 () = (fun verifier -> verifier.VerifyIL [ """ .method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 - ListExpressionSteppingTest6() cil managed - { - - .maxstack 5 - .locals init (valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1 V_0, - class [runtime]System.Collections.Generic.IEnumerator`1 V_1, - class [runtime]System.Collections.Generic.IEnumerable`1 V_2, - int32 V_3, - class [runtime]System.IDisposable V_4) - IL_0000: ldc.i4.1 - IL_0001: ldc.i4.1 - IL_0002: ldc.i4.4 - IL_0003: call class [runtime]System.Collections.Generic.IEnumerable`1 [FSharp.Core]Microsoft.FSharp.Core.Operators/OperatorIntrinsics::RangeInt32(int32, - int32, - int32) - IL_0008: callvirt instance class [runtime]System.Collections.Generic.IEnumerator`1 class [runtime]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_000d: stloc.1 - .try - { - IL_000e: ldloc.1 - IL_000f: callvirt instance bool [runtime]System.Collections.IEnumerator::MoveNext() - IL_0014: brfalse.s IL_0073 + ListExpressionSteppingTest6() cil managed + { + + .maxstack 5 + .locals init (valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1 V_0, + class [runtime]System.Collections.Generic.IEnumerator`1 V_1, + class [runtime]System.Collections.Generic.IEnumerable`1 V_2, + int32 V_3, + class [runtime]System.IDisposable V_4) + IL_0000: ldc.i4.1 + IL_0001: ldc.i4.1 + IL_0002: ldc.i4.4 + IL_0003: call class [runtime]System.Collections.Generic.IEnumerable`1 [FSharp.Core]Microsoft.FSharp.Core.Operators/OperatorIntrinsics::RangeInt32(int32, + int32, + int32) + IL_0008: callvirt instance class [runtime]System.Collections.Generic.IEnumerator`1 class [runtime]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_000d: stloc.1 + .try + { + IL_000e: ldloc.1 + IL_000f: callvirt instance bool [runtime]System.Collections.IEnumerator::MoveNext() + IL_0014: brfalse.s IL_0074 - IL_0016: ldloc.1 - IL_0017: callvirt instance !0 class [runtime]System.Collections.Generic.IEnumerator`1::get_Current() - IL_001c: stloc.3 - IL_001d: ldloc.3 - IL_001e: ldc.i4.1 - IL_001f: sub - IL_0020: switch ( - IL_002f, - IL_004b) - IL_002d: br.s IL_0067 + IL_0016: ldloc.1 + IL_0017: callvirt instance !0 class [runtime]System.Collections.Generic.IEnumerator`1::get_Current() + IL_001c: stloc.3 + IL_001d: ldloc.3 + IL_001e: ldc.i4.1 + IL_001f: sub + IL_0020: switch ( + IL_002f, + IL_004b) + IL_002d: br.s IL_0068 - IL_002f: ldstr "hello" - IL_0034: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) - IL_0039: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_003e: pop - IL_003f: ldloca.s V_0 - IL_0041: ldloc.3 - IL_0042: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Add(!0) - IL_0047: nop - IL_0048: nop - IL_0049: br.s IL_000e + IL_002f: ldstr "hello" + IL_0034: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0039: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_003e: pop + IL_003f: ldloca.s V_0 + IL_0041: ldloc.3 + IL_0042: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Add(!0) + IL_0047: nop + IL_0048: nop + IL_0049: br.s IL_000e - IL_004b: ldstr "hello" - IL_0050: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) - IL_0055: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_005a: pop - IL_005b: ldloca.s V_0 - IL_005d: ldloc.3 - IL_005e: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Add(!0) - IL_0063: nop - IL_0064: nop - IL_0065: br.s IL_000e + IL_004b: nop + IL_004c: ldstr "hello" + IL_0051: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0056: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_005b: pop + IL_005c: ldloca.s V_0 + IL_005e: ldloc.3 + IL_005f: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Add(!0) + IL_0064: nop + IL_0065: nop + IL_0066: br.s IL_000e - IL_0067: ldloca.s V_0 - IL_0069: ldloc.3 - IL_006a: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Add(!0) - IL_006f: nop - IL_0070: nop - IL_0071: br.s IL_000e + IL_0068: ldloca.s V_0 + IL_006a: ldloc.3 + IL_006b: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Add(!0) + IL_0070: nop + IL_0071: nop + IL_0072: br.s IL_000e - IL_0073: ldnull - IL_0074: stloc.2 - IL_0075: leave.s IL_0090 + IL_0074: ldnull + IL_0075: stloc.2 + IL_0076: leave.s IL_008d - } - finally - { - IL_0077: ldloc.1 - IL_0078: isinst [runtime]System.IDisposable - IL_007d: stloc.s V_4 - IL_007f: ldloc.s V_4 - IL_0081: brfalse.s IL_008d + } + finally + { + IL_0078: ldloc.1 + IL_0079: isinst [runtime]System.IDisposable + IL_007e: stloc.s V_4 + IL_0080: ldloc.s V_4 + IL_0082: brfalse.s IL_008c - IL_0083: ldloc.s V_4 - IL_0085: callvirt instance void [runtime]System.IDisposable::Dispose() - IL_008a: ldnull - IL_008b: pop - IL_008c: endfinally - IL_008d: ldnull - IL_008e: pop - IL_008f: endfinally - } - IL_0090: ldloc.2 - IL_0091: pop - IL_0092: ldloca.s V_0 - IL_0094: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() - IL_0099: ret - } + IL_0084: ldloc.s V_4 + IL_0086: callvirt instance void [runtime]System.IDisposable::Dispose() + IL_008b: endfinally + IL_008c: endfinally + } + IL_008d: ldloc.2 + IL_008e: pop + IL_008f: ldloca.s V_0 + IL_0091: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() + IL_0096: ret + } +} """ ]) diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/DelegateAndFuncOptimizations.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/DelegateAndFuncOptimizations.fs new file mode 100644 index 00000000000..be7d5bdbfbf --- /dev/null +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/DelegateAndFuncOptimizations.fs @@ -0,0 +1,530 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests.CodeGen.EmittedIL + +open FSharp.Test.Utilities +open NUnit.Framework + +[] +module DelegateAndFuncOptimizations = + + [] + // See https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1034-lambda-optimizations.md + let ``Reduce function via InlineIfLambda``() = + CompilerAssert.CompileLibraryAndVerifyIL + """ +module InlineIfLambda01 + +open System + +type C = + static member inline M([] f: int -> int) = f 3 + f 4 + static member M2() = C.M(fun x -> x + 1) + static member M3() = + C.M(fun x -> + printfn("code") + printfn("code") + printfn("code") + printfn("code") + printfn("code") + printfn("code") + x + 1) + """ + (fun verifier -> verifier.VerifyIL [ + // Check M is inlined and optimized when small + """ +.method public static int32 M2() cil managed +{ + + .maxstack 8 + IL_0000: ldc.i4.s 9 + IL_0002: ret +} + """ + // Check M is inlined and optimized when largs + """ +.method public static int32 M3() cil managed +{ + + .maxstack 5 + .locals init (class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_0) + IL_0000: ldstr "code" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_000a: stloc.0 + IL_000b: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0010: ldloc.0 + IL_0011: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0016: pop + IL_0017: ldstr "code" + IL_001c: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0021: stloc.0 + IL_0022: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0027: ldloc.0 + IL_0028: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_002d: pop + IL_002e: ldstr "code" + IL_0033: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0038: stloc.0 + IL_0039: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_003e: ldloc.0 + IL_003f: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0044: pop + IL_0045: ldstr "code" + IL_004a: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_004f: stloc.0 + IL_0050: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0055: ldloc.0 + IL_0056: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_005b: pop + IL_005c: ldstr "code" + IL_0061: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0066: stloc.0 + IL_0067: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_006c: ldloc.0 + IL_006d: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0072: pop + IL_0073: ldstr "code" + IL_0078: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_007d: stloc.0 + IL_007e: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0083: ldloc.0 + IL_0084: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0089: pop + IL_008a: ldc.i4.4 + IL_008b: ldstr "code" + IL_0090: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0095: stloc.0 + IL_0096: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_009b: ldloc.0 + IL_009c: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00a1: pop + IL_00a2: ldstr "code" + IL_00a7: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_00ac: stloc.0 + IL_00ad: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_00b2: ldloc.0 + IL_00b3: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00b8: pop + IL_00b9: ldstr "code" + IL_00be: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_00c3: stloc.0 + IL_00c4: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_00c9: ldloc.0 + IL_00ca: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00cf: pop + IL_00d0: ldstr "code" + IL_00d5: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_00da: stloc.0 + IL_00db: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_00e0: ldloc.0 + IL_00e1: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00e6: pop + IL_00e7: ldstr "code" + IL_00ec: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_00f1: stloc.0 + IL_00f2: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_00f7: ldloc.0 + IL_00f8: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00fd: pop + IL_00fe: ldstr "code" + IL_0103: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0108: stloc.0 + IL_0109: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_010e: ldloc.0 + IL_010f: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0114: pop + IL_0115: ldc.i4.5 + IL_0116: add + IL_0117: ret +} + """ + ]) + + [] + // See https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1034-lambda-optimizations.md + let ``Reduce delegate invoke via InlineIfLambda``() = + CompilerAssert.CompileLibraryAndVerifyIL + """ +module InlineIfLambdaOnDelegate + +open System +type D = delegate of int -> int +type C = + static member inline M([] f: D) = f.Invoke 3 + f.Invoke 4 + + // Check M is inlined and optimized when small + static member M2() = C.M(D(fun x -> x + 1)) + + // Check M is inlined and optimized when large + static member M3() = + C.M(D(fun x -> + printfn("code") + printfn("code") + printfn("code") + printfn("code") + printfn("code") + printfn("code") + x + 1)) + """ + (fun verifier -> verifier.VerifyIL [ + // Check M is inlined and optimized when small + """ +.method public static int32 M2() cil managed +{ + + .maxstack 8 + IL_0000: ldc.i4.s 9 + IL_0002: ret +} + """ + // Check M is inlined and optimized when largs + """ +.method public static int32 M3() cil managed +{ + + .maxstack 5 + .locals init (class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_0) + IL_0000: ldstr "code" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_000a: stloc.0 + IL_000b: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0010: ldloc.0 + IL_0011: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0016: pop + IL_0017: ldstr "code" + IL_001c: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0021: stloc.0 + IL_0022: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0027: ldloc.0 + IL_0028: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_002d: pop + IL_002e: ldstr "code" + IL_0033: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0038: stloc.0 + IL_0039: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_003e: ldloc.0 + IL_003f: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0044: pop + IL_0045: ldstr "code" + IL_004a: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_004f: stloc.0 + IL_0050: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0055: ldloc.0 + IL_0056: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_005b: pop + IL_005c: ldstr "code" + IL_0061: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0066: stloc.0 + IL_0067: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_006c: ldloc.0 + IL_006d: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0072: pop + IL_0073: ldstr "code" + IL_0078: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_007d: stloc.0 + IL_007e: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0083: ldloc.0 + IL_0084: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0089: pop + IL_008a: ldc.i4.4 + IL_008b: ldstr "code" + IL_0090: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0095: stloc.0 + IL_0096: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_009b: ldloc.0 + IL_009c: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00a1: pop + IL_00a2: ldstr "code" + IL_00a7: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_00ac: stloc.0 + IL_00ad: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_00b2: ldloc.0 + IL_00b3: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00b8: pop + IL_00b9: ldstr "code" + IL_00be: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_00c3: stloc.0 + IL_00c4: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_00c9: ldloc.0 + IL_00ca: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00cf: pop + IL_00d0: ldstr "code" + IL_00d5: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_00da: stloc.0 + IL_00db: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_00e0: ldloc.0 + IL_00e1: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00e6: pop + IL_00e7: ldstr "code" + IL_00ec: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_00f1: stloc.0 + IL_00f2: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_00f7: ldloc.0 + IL_00f8: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00fd: pop + IL_00fe: ldstr "code" + IL_0103: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0108: stloc.0 + IL_0109: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_010e: ldloc.0 + IL_010f: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0114: pop + IL_0115: ldc.i4.5 + IL_0116: add + IL_0117: ret +} + """ + ]) + + [] + // See https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1034-lambda-optimizations.md + let ``Reduce computed function invoke``() = + CompilerAssert.CompileLibraryAndVerifyIL + """ +module ReduceComputedFunction + +open System + +let ApplyComputedFunction(c: int) = + (let x = c+c in printfn("hello"); (fun y -> x + y)) 3 + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public static int32 ApplyComputedFunction(int32 c) cil managed +{ + + .maxstack 4 + .locals init (int32 V_0, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_1) + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: add + IL_0003: stloc.0 + IL_0004: ldstr "hello" + IL_0009: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_000e: stloc.1 + IL_000f: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0014: ldloc.1 + IL_0015: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_001a: pop + IL_001b: ldloc.0 + IL_001c: ldc.i4.3 + IL_001d: add + IL_001e: ret +} + """ + ]) + + [] + // See https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1034-lambda-optimizations.md + let ``Reduce Computed Delegate``() = + CompilerAssert.CompileLibraryAndVerifyIL + """ +module ReduceComputedDelegate + +open System +type D = delegate of int -> int +let ApplyComputedDelegate(c: int) = + (let x = c+c in printfn("hello"); D(fun y -> x + y)).Invoke 3 + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public static int32 ApplyComputedDelegate(int32 c) cil managed +{ + + .maxstack 4 + .locals init (int32 V_0, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_1) + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: add + IL_0003: stloc.0 + IL_0004: ldstr "hello" + IL_0009: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_000e: stloc.1 + IL_000f: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0014: ldloc.1 + IL_0015: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_001a: pop + IL_001b: ldloc.0 + IL_001c: ldc.i4.3 + IL_001d: add + IL_001e: ret +} + """ + ]) + + [] + // See https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1034-lambda-optimizations.md + let ``Reduce Computed Function with irreducible match``() = + CompilerAssert.CompileLibraryAndVerifyIL + """ +module ReduceComputedFunction + +open System + +let ApplyComputedFunction(c: int) = + (let x = c+c in printfn("hello"); match x with 1 -> (fun y -> x + y) | _ -> (fun y -> x - y)) 3 + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public static int32 ApplyComputedFunction(int32 c) cil managed +{ + + .maxstack 4 + .locals init (int32 V_0, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_1) + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: add + IL_0003: stloc.0 + IL_0004: ldstr "hello" + IL_0009: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_000e: stloc.1 + IL_000f: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0014: ldloc.1 + IL_0015: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_001a: pop + IL_001b: ldloc.0 + IL_001c: ldc.i4.1 + IL_001d: sub + IL_001e: switch ( + IL_0029) + IL_0027: br.s IL_002d + + IL_0029: ldloc.0 + IL_002a: ldc.i4.3 + IL_002b: add + IL_002c: ret + + IL_002d: ldloc.0 + IL_002e: ldc.i4.3 + IL_002f: sub + IL_0030: ret +} + """ + ]) + + + [] + // See https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1034-lambda-optimizations.md + let ``Immediately apply computed function in sequential``() = + CompilerAssert.CompileLibraryAndVerifyIL + """ +module ImmediatelyApplyComputedFunction + +open System + +let ApplyComputedFunction(c: int) = + let part1 = match c with 1 -> (fun y -> printfn("a")) | _ -> (fun y -> printfn("b")) + part1 3 + printfn("done!") + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public static void ApplyComputedFunction(int32 c) cil managed +{ + + .maxstack 4 + .locals init (class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_0) + IL_0000: ldarg.0 + IL_0001: ldc.i4.1 + IL_0002: sub + IL_0003: switch ( + IL_000e) + IL_000c: br.s IL_0027 + + IL_000e: ldstr "a" + IL_0013: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0018: stloc.0 + IL_0019: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_001e: ldloc.0 + IL_001f: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0024: pop + IL_0025: br.s IL_003e + + IL_0027: ldstr "b" + IL_002c: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0031: stloc.0 + IL_0032: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0037: ldloc.0 + IL_0038: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_003d: pop + IL_003e: ldstr "done!" + IL_0043: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0048: stloc.0 + IL_0049: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_004e: ldloc.0 + IL_004f: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0054: pop + IL_0055: ret +} + """ + ]) + + [] + // See https://github.com/fsharp/fslang-design/blob/master/tooling/FST-1034-lambda-optimizations.md + let ``Reduce Computed Delegate with let rec``() = + CompilerAssert.CompileLibraryAndVerifyIL + """ +module ReduceComputedDelegate + +open System +type D = delegate of int -> int +let ApplyComputedDelegate(c: int) = + (let rec f x = if x = 0 then x else f (x-1) in printfn("hello"); D(fun y -> f c + y)).Invoke 3 + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public static int32 ApplyComputedDelegate(int32 c) cil managed +{ + + .maxstack 4 + .locals init (class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_0) + IL_0000: ldstr "hello" + IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_000a: stloc.0 + IL_000b: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0010: ldloc.0 + IL_0011: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter(class [runtime]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0016: pop + IL_0017: ldarg.0 + IL_0018: call int32 ReduceComputedDelegate::f@7(int32) + IL_001d: ldc.i4.3 + IL_001e: add + IL_001f: ret +} + """ + ]) + diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/StaticMember.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/StaticMember.fs index b1415c0e929..459972bf5c6 100644 --- a/tests/fsharp/Compiler/CodeGen/EmittedIL/StaticMember.fs +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/StaticMember.fs @@ -88,30 +88,35 @@ type MyClass(x: int32) = [] let main _ = -let input = new MyClass(7) -let func = new Action(fun x -> C.M input.X) -0 + let input = new MyClass(7) + let func = new Action(fun x -> C.M input.X) + box func |> ignore // make sure 'func' is not optimized away + 0 """ (fun verifier -> verifier.VerifyIL [ """ .method public static int32 main(string[] _arg1) cil managed { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.EntryPointAttribute::.ctor() = ( 01 00 00 00 ) - + .maxstack 4 .locals init (class StaticMember03/MyClass V_0, - class [runtime]System.Action`1 V_1) + class [runtime]System.Action`1 V_1, + object V_2) IL_0000: ldc.i4.7 IL_0001: newobj instance void StaticMember03/MyClass::.ctor(int32) IL_0006: stloc.0 IL_0007: ldnull IL_0008: ldftn void StaticMember03/func@15::Invoke(int32) IL_000e: newobj instance void class [runtime]System.Action`1::.ctor(object, - native int) + native int) IL_0013: stloc.1 - IL_0014: ldc.i4.0 - IL_0015: ret -} + IL_0014: ldloc.1 + IL_0015: box class [runtime]System.Action`1 + IL_001a: stloc.2 + IL_001b: ldc.i4.0 + IL_001c: ret +} """ """ .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname func@15 @@ -204,6 +209,7 @@ type MyClass(x: int32) = let main _ = let input = new MyClass(7) let func = new Func(fun x -> C.M input.X) + box func |> ignore // dummy code to prevent func being optimized away 0 """ (fun verifier -> verifier.VerifyIL [ @@ -211,10 +217,11 @@ let main _ = .method public static int32 main(string[] _arg1) cil managed { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.EntryPointAttribute::.ctor() = ( 01 00 00 00 ) - + .maxstack 4 .locals init (class StaticMember06/MyClass V_0, - class [runtime]System.Func`2 V_1) + class [runtime]System.Func`2 V_1, + object V_2) IL_0000: ldc.i4.7 IL_0001: newobj instance void StaticMember06/MyClass::.ctor(int32) IL_0006: stloc.0 @@ -222,11 +229,14 @@ let main _ = IL_0008: newobj instance void StaticMember06/func@16::.ctor(class StaticMember06/MyClass) IL_000d: ldftn instance int32 StaticMember06/func@16::Invoke(int32) IL_0013: newobj instance void class [runtime]System.Func`2::.ctor(object, - native int) + native int) IL_0018: stloc.1 - IL_0019: ldc.i4.0 - IL_001a: ret -} + IL_0019: ldloc.1 + IL_001a: box class [runtime]System.Func`2 + IL_001f: stloc.2 + IL_0020: ldc.i4.0 + IL_0021: ret +} """ """ .class auto autochar serializable sealed nested assembly beforefieldinit specialname func@16 diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs new file mode 100644 index 00000000000..1c59c9703e2 --- /dev/null +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs @@ -0,0 +1,1141 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.UnitTests.CodeGen.EmittedIL + +open FSharp.Test.Utilities +open NUnit.Framework + +open System +open System.Threading.Tasks + +// These tests are sensitive to the fact that FSharp.Core is compiled release, not debug +// The code generated changes slightly in debug mode +#if !DEBUG +// Check the exact code produced for tasks +[] +module TaskGeneratedCode = + + // This tests the exact optimized code generated for the MoveNext for a trivial task - we expect 'MoveNext' to be there + // because state machine compilation succeeds + // + // The code is not perfect - because the MoveNext is generated late - but the JIT does a good job on it. + // + // The try/catch for the task still exists even though there is no chance of an exception + // + // The crucial code for "return 1" is really just + // IL_000e: ldc.i4.1 + // IL_000f: stfld int32 Test/testTask@4::Result + + [] + let ``check MoveNext of simple task debug``() = + CompilerAssert.CompileLibraryAndVerifyILWithOptions [| "/langversion:preview";"/optimize-";"/debug:portable";"/tailcalls-" |] + """ +module Test + +let testTask() = task { return 1 } + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public strict virtual instance void +MoveNext() cil managed +{ + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext + + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + int32 V_3, + class [runtime]System.Exception V_4, + class [runtime]System.Exception V_5) + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldc.i4.1 + IL_0008: stloc.3 + IL_0009: ldarg.0 + IL_000a: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_000f: ldloc.3 + IL_0010: stfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_0015: ldc.i4.1 + IL_0016: stloc.2 + IL_0017: ldloc.2 + IL_0018: brfalse.s IL_0037 + + IL_001a: ldarg.0 + IL_001b: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0020: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0025: ldarg.0 + IL_0026: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_002b: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_0030: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_0035: leave.s IL_0045 + + IL_0037: leave.s IL_0045 + + } + catch [runtime]System.Object + { + IL_0039: castclass [runtime]System.Exception + IL_003e: stloc.s V_4 + IL_0040: ldloc.s V_4 + IL_0042: stloc.1 + IL_0043: leave.s IL_0045 + + } + IL_0045: ldloc.1 + IL_0046: stloc.s V_5 + IL_0048: ldloc.s V_5 + IL_004a: brtrue.s IL_004d + + IL_004c: ret + + IL_004d: ldarg.0 + IL_004e: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0053: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0058: ldloc.s V_5 + IL_005a: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_005f: ret +} + """ + ]) + + // This tests the exact optimized code generated for the MoveNext for a trivial task - we expect 'MoveNext' to be there + // because state machine compilation succeeds + // + // The code is not perfect - because the MoveNext is generated late - but the JIT does a good job on it. + // + // The try/catch for the task still exists even though there is no chance of an exception + // + // The crucial code for "return 1" is really just + // IL_000e: ldc.i4.1 + // IL_000f: stfld int32 Test/testTask@4::Result + + [] + let ``check MoveNext of simple task optimized``() = + CompilerAssert.CompileLibraryAndVerifyILWithOptions [| "/langversion:preview";"/optimize+";"/debug:portable";"/tailcalls+" |] + """ +module Test + +let testTask() = task { return 1 } + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public strict virtual instance void + MoveNext() cil managed +{ + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext + + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + class [runtime]System.Exception V_3) + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldarg.0 + IL_0008: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_000d: ldc.i4.1 + IL_000e: stfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_0013: ldc.i4.1 + IL_0014: stloc.2 + IL_0015: ldloc.2 + IL_0016: brfalse.s IL_0035 + + IL_0018: ldarg.0 + IL_0019: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_001e: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0023: ldarg.0 + IL_0024: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0029: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_002e: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_0033: leave.s IL_0041 + + IL_0035: leave.s IL_0041 + + } + catch [runtime]System.Object + { + IL_0037: castclass [runtime]System.Exception + IL_003c: stloc.3 + IL_003d: ldloc.3 + IL_003e: stloc.1 + IL_003f: leave.s IL_0041 + + } + IL_0041: ldloc.1 + IL_0042: stloc.3 + IL_0043: ldloc.3 + IL_0044: brtrue.s IL_0047 + + IL_0046: ret + + IL_0047: ldarg.0 + IL_0048: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_004d: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0052: ldloc.3 + IL_0053: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_0058: ret +} + """ + ]) + + + [] + let ``check MoveNext of simple binding task debug``() = + CompilerAssert.CompileLibraryAndVerifyILWithOptions [| "/langversion:preview"; "/debug:portable"; "/optimize-"; "/tailcalls-" |] + """ +module Test +open System.Threading.Tasks +let testTask(t: Task) = task { let! res = t in return res+1 } + """ + (fun verifier -> verifier.VerifyIL [ + """ + .method public strict virtual instance void + MoveNext() cil managed + { + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext + + .maxstack 5 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + class [runtime]System.Threading.Tasks.Task`1 V_3, + bool V_4, + bool V_5, + int32 V_6, + int32 V_7, + int32 V_8, + int32 V_9, + valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 V_10, + class [runtime]System.Exception V_11, + class [runtime]System.Exception V_12) + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: ldc.i4.1 + IL_0009: sub + IL_000a: switch ( + IL_0015) + IL_0013: br.s IL_0018 + + IL_0015: nop + IL_0016: br.s IL_0019 + + IL_0018: nop + .try + { + IL_0019: ldloc.0 + IL_001a: ldc.i4.1 + IL_001b: sub + IL_001c: switch ( + IL_0027) + IL_0025: br.s IL_002a + + IL_0027: nop + IL_0028: br.s IL_0053 + + IL_002a: nop + IL_002b: ldarg.0 + IL_002c: ldfld class [runtime]System.Threading.Tasks.Task`1 Test/testTask@4::t + IL_0031: stloc.3 + IL_0032: ldarg.0 + IL_0033: ldloc.3 + IL_0034: callvirt instance valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1 class [netstandard]System.Threading.Tasks.Task`1::GetAwaiter() + IL_0039: stfld valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 Test/testTask@4::awaiter + IL_003e: ldc.i4.1 + IL_003f: stloc.s V_4 + IL_0041: ldarg.0 + IL_0042: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 Test/testTask@4::awaiter + IL_0047: call instance bool valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1::get_IsCompleted() + IL_004c: brfalse.s IL_0050 + + IL_004e: br.s IL_0069 + + IL_0050: ldc.i4.0 + IL_0051: brfalse.s IL_0057 + + IL_0053: ldc.i4.1 + IL_0054: nop + IL_0055: br.s IL_0060 + + IL_0057: ldarg.0 + IL_0058: ldc.i4.1 + IL_0059: stfld int32 Test/testTask@4::ResumptionPoint + IL_005e: ldc.i4.0 + IL_005f: nop + IL_0060: stloc.s V_5 + IL_0062: ldloc.s V_5 + IL_0064: stloc.s V_4 + IL_0066: nop + IL_0067: br.s IL_006a + + IL_0069: nop + IL_006a: ldloc.s V_4 + IL_006c: brfalse.s IL_009a + + IL_006e: ldarg.0 + IL_006f: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 Test/testTask@4::awaiter + IL_0074: call instance !0 valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1::GetResult() + IL_0079: stloc.s V_6 + IL_007b: ldloc.s V_6 + IL_007d: stloc.s V_7 + IL_007f: ldloc.s V_7 + IL_0081: stloc.s V_8 + IL_0083: ldloc.s V_8 + IL_0085: ldc.i4.1 + IL_0086: add + IL_0087: stloc.s V_9 + IL_0089: ldarg.0 + IL_008a: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_008f: ldloc.s V_9 + IL_0091: stfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_0096: ldc.i4.1 + IL_0097: nop + IL_0098: br.s IL_00b3 + + IL_009a: ldarg.0 + IL_009b: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_00a0: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_00a5: ldarg.0 + IL_00a6: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 Test/testTask@4::awaiter + IL_00ab: ldarg.0 + IL_00ac: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::AwaitUnsafeOnCompleted,valuetype Test/testTask@4>(!!0&, + !!1&) + IL_00b1: ldc.i4.0 + IL_00b2: nop + IL_00b3: brfalse.s IL_00c1 + + IL_00b5: ldarg.0 + IL_00b6: ldloc.s V_10 + IL_00b8: stfld valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 Test/testTask@4::awaiter + IL_00bd: ldc.i4.1 + IL_00be: nop + IL_00bf: br.s IL_00c3 + + IL_00c1: ldc.i4.0 + IL_00c2: nop + IL_00c3: stloc.2 + IL_00c4: ldloc.2 + IL_00c5: brfalse.s IL_00e4 + + IL_00c7: ldarg.0 + IL_00c8: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_00cd: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_00d2: ldarg.0 + IL_00d3: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_00d8: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_00dd: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_00e2: leave.s IL_00f2 + + IL_00e4: leave.s IL_00f2 + + } + catch [runtime]System.Object + { + IL_00e6: castclass [runtime]System.Exception + IL_00eb: stloc.s V_11 + IL_00ed: ldloc.s V_11 + IL_00ef: stloc.1 + IL_00f0: leave.s IL_00f2 + + } + IL_00f2: ldloc.1 + IL_00f3: stloc.s V_12 + IL_00f5: ldloc.s V_12 + IL_00f7: brtrue.s IL_00fa + + IL_00f9: ret + + IL_00fa: ldarg.0 + IL_00fb: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0100: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0105: ldloc.s V_12 + IL_0107: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_010c: ret + } + """ + ]) + +module TaskTryFinallyGeneration = + + [] + let ``check MoveNext of task try/finally optimized``() = + CompilerAssert.CompileLibraryAndVerifyILWithOptions [| "/langversion:preview";"/optimize+";"/debug:portable";"/tailcalls+" |] + """ +module Test + +let testTask() = task { try 1+1 finally System.Console.WriteLine("finally") } + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public strict virtual instance void + MoveNext() cil managed +{ + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext + + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + bool V_3, + bool V_4, + class [runtime]System.Exception V_5) + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldc.i4.0 + IL_0008: stloc.3 + IL_0009: ldloc.3 + IL_000a: brfalse.s IL_0010 + + IL_000c: ldc.i4.1 + IL_000d: nop + IL_000e: br.s IL_0012 + + IL_0010: ldloc.3 + IL_0011: nop + IL_0012: stloc.3 + .try + { + IL_0013: nop + IL_0014: ldc.i4.1 + IL_0015: stloc.s V_4 + IL_0017: ldloc.s V_4 + IL_0019: stloc.3 + IL_001a: leave.s IL_003b + + } + catch [runtime]System.Object + { + IL_001c: castclass [runtime]System.Exception + IL_0021: stloc.s V_5 + IL_0023: ldstr "finally" + IL_0028: call void [runtime]System.Console::WriteLine(string) + IL_002d: ldc.i4.1 + IL_002e: stloc.s V_4 + IL_0030: rethrow + IL_0032: ldnull + IL_0033: unbox.any [FSharp.Core]Microsoft.FSharp.Core.Unit + IL_0038: pop + IL_0039: leave.s IL_003b + + } + IL_003b: ldloc.3 + IL_003c: brfalse.s IL_004e + + IL_003e: ldstr "finally" + IL_0043: call void [runtime]System.Console::WriteLine(string) + IL_0048: ldc.i4.1 + IL_0049: stloc.s V_4 + IL_004b: nop + IL_004c: br.s IL_004f + + IL_004e: nop + IL_004f: ldloc.3 + IL_0050: stloc.2 + IL_0051: ldloc.2 + IL_0052: brfalse.s IL_0071 + + IL_0054: ldarg.0 + IL_0055: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_005a: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_005f: ldarg.0 + IL_0060: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0065: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_006a: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_006f: leave.s IL_007f + + IL_0071: leave.s IL_007f + + } + catch [runtime]System.Object + { + IL_0073: castclass [runtime]System.Exception + IL_0078: stloc.s V_5 + IL_007a: ldloc.s V_5 + IL_007c: stloc.1 + IL_007d: leave.s IL_007f + + } + IL_007f: ldloc.1 + IL_0080: stloc.s V_5 + IL_0082: ldloc.s V_5 + IL_0084: brtrue.s IL_0087 + + IL_0086: ret + + IL_0087: ldarg.0 + IL_0088: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_008d: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0092: ldloc.s V_5 + IL_0094: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_0099: ret +} + """ + ]) + + + [] + let ``check MoveNext of task try/finally debug``() = + CompilerAssert.CompileLibraryAndVerifyILWithOptions [| "/langversion:preview";"/optimize-";"/debug:portable";"/tailcalls-" |] + """ +module Test + +let testTask() = task { try 1+1 finally System.Console.WriteLine("finally") } + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public strict virtual instance void + MoveNext() cil managed +{ + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext + + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + bool V_3, + bool V_4, + class [runtime]System.Exception V_5, + bool V_6, + bool V_7, + class [runtime]System.Exception V_8, + class [runtime]System.Exception V_9) + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldc.i4.0 + IL_0008: stloc.3 + IL_0009: ldloc.3 + IL_000a: brfalse.s IL_0010 + + IL_000c: ldc.i4.1 + IL_000d: nop + IL_000e: br.s IL_0012 + + IL_0010: ldloc.3 + IL_0011: nop + IL_0012: stloc.3 + .try + { + IL_0013: nop + IL_0014: ldc.i4.1 + IL_0015: stloc.s V_4 + IL_0017: ldloc.s V_4 + IL_0019: stloc.3 + IL_001a: leave.s IL_003b + + } + catch [runtime]System.Object + { + IL_001c: castclass [runtime]System.Exception + IL_0021: stloc.s V_5 + IL_0023: ldstr "finally" + IL_0028: call void [runtime]System.Console::WriteLine(string) + IL_002d: ldc.i4.1 + IL_002e: stloc.s V_6 + IL_0030: rethrow + IL_0032: ldnull + IL_0033: unbox.any [FSharp.Core]Microsoft.FSharp.Core.Unit + IL_0038: pop + IL_0039: leave.s IL_003b + + } + IL_003b: ldloc.3 + IL_003c: brfalse.s IL_004e + + IL_003e: ldstr "finally" + IL_0043: call void [runtime]System.Console::WriteLine(string) + IL_0048: ldc.i4.1 + IL_0049: stloc.s V_7 + IL_004b: nop + IL_004c: br.s IL_004f + + IL_004e: nop + IL_004f: ldloc.3 + IL_0050: stloc.2 + IL_0051: ldloc.2 + IL_0052: brfalse.s IL_0071 + + IL_0054: ldarg.0 + IL_0055: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_005a: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_005f: ldarg.0 + IL_0060: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0065: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_006a: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_006f: leave.s IL_007f + + IL_0071: leave.s IL_007f + + } + catch [runtime]System.Object + { + IL_0073: castclass [runtime]System.Exception + IL_0078: stloc.s V_8 + IL_007a: ldloc.s V_8 + IL_007c: stloc.1 + IL_007d: leave.s IL_007f + + } + IL_007f: ldloc.1 + IL_0080: stloc.s V_9 + IL_0082: ldloc.s V_9 + IL_0084: brtrue.s IL_0087 + + IL_0086: ret + + IL_0087: ldarg.0 + IL_0088: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_008d: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0092: ldloc.s V_9 + IL_0094: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_0099: ret +} + """ + ]) + +module TaskTryWithGeneration = + + [] + let ``check MoveNext of task try/with optimized``() = + CompilerAssert.CompileLibraryAndVerifyILWithOptions [| "/langversion:preview";"/optimize+";"/debug:portable";"/tailcalls+" |] + """ +module Test + +let testTask() = task { try 1 with e -> System.Console.WriteLine("finally"); 2 } + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public strict virtual instance void + MoveNext() cil managed +{ + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext + + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + bool V_3, + bool V_4, + class [runtime]System.Exception V_5, + bool V_6, + class [runtime]System.Exception V_7) + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldc.i4.0 + IL_0008: stloc.3 + IL_0009: ldc.i4.0 + IL_000a: stloc.s V_4 + IL_000c: ldnull + IL_000d: stloc.s V_5 + IL_000f: ldloc.3 + IL_0010: brfalse.s IL_0016 + + IL_0012: ldc.i4.1 + IL_0013: nop + IL_0014: br.s IL_0018 + + IL_0016: ldloc.3 + IL_0017: nop + IL_0018: stloc.3 + .try + { + IL_0019: nop + IL_001a: ldc.i4.1 + IL_001b: stloc.s V_6 + IL_001d: ldloc.s V_6 + IL_001f: stloc.3 + IL_0020: leave.s IL_0032 + + } + catch [runtime]System.Object + { + IL_0022: castclass [runtime]System.Exception + IL_0027: stloc.s V_7 + IL_0029: ldc.i4.1 + IL_002a: stloc.s V_4 + IL_002c: ldloc.s V_7 + IL_002e: stloc.s V_5 + IL_0030: leave.s IL_0032 + + } + IL_0032: ldloc.s V_4 + IL_0034: brfalse.s IL_0048 + + IL_0036: ldloc.s V_5 + IL_0038: stloc.s V_7 + IL_003a: ldstr "finally" + IL_003f: call void [runtime]System.Console::WriteLine(string) + IL_0044: ldc.i4.1 + IL_0045: nop + IL_0046: br.s IL_004a + + IL_0048: ldloc.3 + IL_0049: nop + IL_004a: stloc.2 + IL_004b: ldloc.2 + IL_004c: brfalse.s IL_006b + + IL_004e: ldarg.0 + IL_004f: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0054: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0059: ldarg.0 + IL_005a: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_005f: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_0064: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_0069: leave.s IL_0079 + + IL_006b: leave.s IL_0079 + + } + catch [runtime]System.Object + { + IL_006d: castclass [runtime]System.Exception + IL_0072: stloc.s V_5 + IL_0074: ldloc.s V_5 + IL_0076: stloc.1 + IL_0077: leave.s IL_0079 + + } + IL_0079: ldloc.1 + IL_007a: stloc.s V_5 + IL_007c: ldloc.s V_5 + IL_007e: brtrue.s IL_0081 + + IL_0080: ret + + IL_0081: ldarg.0 + IL_0082: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0087: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_008c: ldloc.s V_5 + IL_008e: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_0093: ret +} + """ + ]) + + + [] + let ``check MoveNext of task try/with debug``() = + CompilerAssert.CompileLibraryAndVerifyILWithOptions [| "/langversion:preview";"/optimize-";"/debug:portable";"/tailcalls-" |] + """ +module Test + +let testTask() = task { try 1 with e -> System.Console.WriteLine("with"); 2 } + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public strict virtual instance void + MoveNext() cil managed +{ + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext + + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + bool V_3, + bool V_4, + class [runtime]System.Exception V_5, + bool V_6, + class [runtime]System.Exception V_7, + class [runtime]System.Exception V_8, + class [runtime]System.Exception V_9, + class [runtime]System.Exception V_10, + class [runtime]System.Exception V_11) + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldc.i4.0 + IL_0008: stloc.3 + IL_0009: ldc.i4.0 + IL_000a: stloc.s V_4 + IL_000c: ldnull + IL_000d: stloc.s V_5 + IL_000f: ldloc.3 + IL_0010: brfalse.s IL_0016 + + IL_0012: ldc.i4.1 + IL_0013: nop + IL_0014: br.s IL_0018 + + IL_0016: ldloc.3 + IL_0017: nop + IL_0018: stloc.3 + .try + { + IL_0019: nop + IL_001a: ldc.i4.1 + IL_001b: stloc.s V_6 + IL_001d: ldloc.s V_6 + IL_001f: stloc.3 + IL_0020: leave.s IL_0032 + + } + catch [runtime]System.Object + { + IL_0022: castclass [runtime]System.Exception + IL_0027: stloc.s V_7 + IL_0029: ldc.i4.1 + IL_002a: stloc.s V_4 + IL_002c: ldloc.s V_7 + IL_002e: stloc.s V_5 + IL_0030: leave.s IL_0032 + + } + IL_0032: ldloc.s V_4 + IL_0034: brfalse.s IL_004c + + IL_0036: ldloc.s V_5 + IL_0038: stloc.s V_8 + IL_003a: ldloc.s V_8 + IL_003c: stloc.s V_9 + IL_003e: ldstr "with" + IL_0043: call void [runtime]System.Console::WriteLine(string) + IL_0048: ldc.i4.1 + IL_0049: nop + IL_004a: br.s IL_004e + + IL_004c: ldloc.3 + IL_004d: nop + IL_004e: stloc.2 + IL_004f: ldloc.2 + IL_0050: brfalse.s IL_006f + + IL_0052: ldarg.0 + IL_0053: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0058: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_005d: ldarg.0 + IL_005e: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0063: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_0068: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_006d: leave.s IL_007d + + IL_006f: leave.s IL_007d + + } + catch [runtime]System.Object + { + IL_0071: castclass [runtime]System.Exception + IL_0076: stloc.s V_10 + IL_0078: ldloc.s V_10 + IL_007a: stloc.1 + IL_007b: leave.s IL_007d + + } + IL_007d: ldloc.1 + IL_007e: stloc.s V_11 + IL_0080: ldloc.s V_11 + IL_0082: brtrue.s IL_0085 + + IL_0084: ret + + IL_0085: ldarg.0 + IL_0086: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_008b: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0090: ldloc.s V_11 + IL_0092: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_0097: ret +} + """ + ]) + +module TaskWhileLoopGeneration = + + [] + let ``check MoveNext of task while loop optimized``() = + CompilerAssert.CompileLibraryAndVerifyILWithOptions [| "/langversion:preview";"/optimize+";"/debug:portable";"/tailcalls+" |] + """ +module Test + +let mutable x = 1 +let testTask() = task { while x > 4 do System.Console.WriteLine("loop") } + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public strict virtual instance void + MoveNext() cil managed +{ + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext + + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + bool V_3, + bool V_4, + class [runtime]System.Exception V_5) + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@5::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldc.i4.1 + IL_0008: stloc.3 + IL_0009: ldloc.3 + IL_000a: brfalse.s IL_0017 + + IL_000c: call int32 Test::get_x() + IL_0011: ldc.i4.4 + IL_0012: cgt + IL_0014: nop + IL_0015: br.s IL_0019 + + IL_0017: ldc.i4.0 + IL_0018: nop + IL_0019: brfalse.s IL_0030 + + IL_001b: ldstr "loop" + IL_0020: call void [runtime]System.Console::WriteLine(string) + IL_0025: ldc.i4.1 + IL_0026: stloc.s V_4 + IL_0028: ldloc.s V_4 + IL_002a: stloc.3 + IL_002b: ldc.i4.0 + IL_002c: stloc.0 + IL_002d: nop + IL_002e: br.s IL_0009 + + IL_0030: ldloc.3 + IL_0031: stloc.2 + IL_0032: ldloc.2 + IL_0033: brfalse.s IL_0052 + + IL_0035: ldarg.0 + IL_0036: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_003b: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0040: ldarg.0 + IL_0041: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_0046: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_004b: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_0050: leave.s IL_0060 + + IL_0052: leave.s IL_0060 + + } + catch [runtime]System.Object + { + IL_0054: castclass [runtime]System.Exception + IL_0059: stloc.s V_5 + IL_005b: ldloc.s V_5 + IL_005d: stloc.1 + IL_005e: leave.s IL_0060 + + } + IL_0060: ldloc.1 + IL_0061: stloc.s V_5 + IL_0063: ldloc.s V_5 + IL_0065: brtrue.s IL_0068 + + IL_0067: ret + + IL_0068: ldarg.0 + IL_0069: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_006e: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0073: ldloc.s V_5 + IL_0075: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_007a: ret +} + """ + ]) + + + [] + let ``check MoveNext of task while loop debug``() = + CompilerAssert.CompileLibraryAndVerifyILWithOptions [| "/langversion:preview";"/optimize-";"/debug:portable";"/tailcalls-" |] + """ +module Test + +let mutable x = 1 +let testTask() = task { while x > 4 do System.Console.WriteLine("loop") } + """ + (fun verifier -> verifier.VerifyIL [ + """ +.method public strict virtual instance void + MoveNext() cil managed +{ + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext + + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + bool V_3, + bool V_4, + class [runtime]System.Exception V_5, + class [runtime]System.Exception V_6) + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@5::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldc.i4.1 + IL_0008: stloc.3 + IL_0009: ldloc.3 + IL_000a: brfalse.s IL_0017 + + IL_000c: call int32 Test::get_x() + IL_0011: ldc.i4.4 + IL_0012: cgt + IL_0014: nop + IL_0015: br.s IL_0019 + + IL_0017: ldc.i4.0 + IL_0018: nop + IL_0019: brfalse.s IL_0030 + + IL_001b: ldstr "loop" + IL_0020: call void [runtime]System.Console::WriteLine(string) + IL_0025: ldc.i4.1 + IL_0026: stloc.s V_4 + IL_0028: ldloc.s V_4 + IL_002a: stloc.3 + IL_002b: ldc.i4.0 + IL_002c: stloc.0 + IL_002d: nop + IL_002e: br.s IL_0009 + + IL_0030: ldloc.3 + IL_0031: stloc.2 + IL_0032: ldloc.2 + IL_0033: brfalse.s IL_0052 + + IL_0035: ldarg.0 + IL_0036: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_003b: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0040: ldarg.0 + IL_0041: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_0046: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_004b: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_0050: leave.s IL_0060 + + IL_0052: leave.s IL_0060 + + } + catch [runtime]System.Object + { + IL_0054: castclass [runtime]System.Exception + IL_0059: stloc.s V_5 + IL_005b: ldloc.s V_5 + IL_005d: stloc.1 + IL_005e: leave.s IL_0060 + + } + IL_0060: ldloc.1 + IL_0061: stloc.s V_6 + IL_0063: ldloc.s V_6 + IL_0065: brtrue.s IL_0068 + + IL_0067: ret + + IL_0068: ldarg.0 + IL_0069: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_006e: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0073: ldloc.s V_6 + IL_0075: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_007a: ret +} + """ + ]) +#endif + + +#if NETCOREAPP +[] +module ``Check stack traces`` = + [] + let ``check stack trace of async exception from task``() = + let t() = + task { + let! throws = task { + do! System.Threading.Tasks.Task.Yield() + failwith "Inner task exception" + return () + } + return throws + } + + let f() = t().Wait() + + let stackTrace = try f(); failwith "huh?" with e -> e.ToString() + + if stackTrace.Contains("huh?") then + failwith "unexpected - inner exception not generated correctly" + + if not (stackTrace.Contains("MoveNext()")) then + failwith "expected MoveNext() on stack trace" + + if stackTrace.Contains("End of stack trace from previous location") then + failwith "expected emit of CompilerGeneratedAtrtibute to suppress message in .NET Core stack walking " +#endif + + +// Test that the SRTP Bind on a ValueTask is still generic in the bind type +[] +module ``Check return attributes`` = + let incr (x:int) : [] (int -> int) = (fun a -> a + x) + + // Putting a return atribute of any kind on f function should be respected + // If the function is curried its inferred arity should be no more than + // the declared arguments (the F# rule that infers additional arguments + // should not kick in). + [] + let ``check return attribute of curried function``() = + match <@ incr 3 4 @> with + | Quotations.Patterns.Application (Quotations.Patterns.Call(None, mi, [Quotations.DerivedPatterns.Int32 3]), Quotations.DerivedPatterns.Int32 4) -> + if mi.GetParameters().Length <> 1 then + failwith "wrong number of parameters" + if mi.ReturnTypeCustomAttributes.GetCustomAttributes(false).Length <> 1 then + failwith "wrong number of attributes" + () + | _ -> failwith "curried function expected" + + +// Compilation test +// Test that the SRTP Bind on a ValueTask is still generic in the bind type +module ``SRTP Bind on a ValueTask is still generic in the bind type (nested)`` = + let FindAsync() = ValueTask<'T>(Unchecked.defaultof<'T>) + let TryFindAsync() : Task<'T voption> = task { + let! r = FindAsync() + if obj.ReferenceEquals(r, null) then return ValueNone + else return ValueSome r + } + let t1 : Task = TryFindAsync() // test TryFindAsync is generic + let t2 : Task = TryFindAsync() // test TryFindAsync is generic + +// Compilation test +// Test that the SRTP Bind on a ValueTask is still generic in the bind type +module ``SRTP Bind on a ValueTask is still generic in the bind type`` = + let FindAsync() = ValueTask<'T>(Unchecked.defaultof<'T>) + let TryFindAsync() : Task<'T> = task { + let! r = FindAsync() + return r + } + +// Compilation test +module ``SRTP ReturnFrom on a ValueTask is still generic in the bind type`` = + let FindAsync() = ValueTask<'T>(Unchecked.defaultof<'T>) + let TryFindAsync() : Task<'T> = task { + return! FindAsync() + } + + let t1 : Task = TryFindAsync() // test TryFindAsync is generic + let t2 : Task = TryFindAsync() // test TryFindAsync is generic + diff --git a/tests/fsharp/Compiler/Language/OptionalInteropTests.fs b/tests/fsharp/Compiler/Language/OptionalInteropTests.fs index 72fa7ee3b20..17dcfd4f62e 100644 --- a/tests/fsharp/Compiler/Language/OptionalInteropTests.fs +++ b/tests/fsharp/Compiler/Language/OptionalInteropTests.fs @@ -152,7 +152,7 @@ Test.MethodTakingNullables(Nullable 6, y="aaaaaa", d=8.0) |> ignore |> MetadataReference.CreateFromFile let cs = - CompilationUtil.CreateCSharpCompilation(csSrc, CSharpLanguageVersion.CSharp8, TargetFramework.NetStandard20, additionalReferences = ImmutableArray.CreateRange [fsharpCoreAssembly]) + CompilationUtil.CreateCSharpCompilation(csSrc, CSharpLanguageVersion.CSharp8, TargetFramework.NetCoreApp31, additionalReferences = ImmutableArray.CreateRange [fsharpCoreAssembly]) |> CompilationReference.Create let fs = Compilation.Create(fsSrc, SourceKind.Fsx, CompileOutput.Exe, options = [|"--langversion:5.0"|], cmplRefs = [cs]) diff --git a/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs b/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs index 1eec3bd3c6b..6d155dc723e 100644 --- a/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs +++ b/tests/fsharp/Compiler/Language/SpanOptimizationTests.fs @@ -158,59 +158,54 @@ module Test = (fun verifier -> verifier.VerifyIL [ - """.method public static void test() cil managed - { - - .maxstack 3 - .locals init (valuetype System.Span`1 V_0, - class [System.Runtime]System.Collections.IEnumerator V_1, - class [FSharp.Core]Microsoft.FSharp.Core.Unit V_2, - class [System.Runtime]System.IDisposable V_3) - IL_0000: call !!0[] [runtime]System.Array::Empty() - IL_0005: newobj instance void valuetype System.Span`1::.ctor(!0[]) - IL_000a: stloc.0 - IL_000b: ldloc.0 - IL_000c: box valuetype System.Span`1 - IL_0011: unbox.any [System.Runtime]System.Collections.IEnumerable - IL_0016: callvirt instance class [System.Runtime]System.Collections.IEnumerator [System.Runtime]System.Collections.IEnumerable::GetEnumerator() - IL_001b: stloc.1 - .try - { - IL_001c: ldloc.1 - IL_001d: callvirt instance bool [System.Runtime]System.Collections.IEnumerator::MoveNext() - IL_0022: brfalse.s IL_0031 - - IL_0024: ldloc.1 - IL_0025: callvirt instance object [System.Runtime]System.Collections.IEnumerator::get_Current() - IL_002a: call void [System.Console]System.Console::WriteLine(object) - IL_002f: br.s IL_001c - - IL_0031: ldnull - IL_0032: stloc.2 - IL_0033: leave.s IL_004b - - } - finally - { - IL_0035: ldloc.1 - IL_0036: isinst [System.Runtime]System.IDisposable - IL_003b: stloc.3 - IL_003c: ldloc.3 - IL_003d: brfalse.s IL_0048 - - IL_003f: ldloc.3 - IL_0040: callvirt instance void [System.Runtime]System.IDisposable::Dispose() - IL_0045: ldnull - IL_0046: pop - IL_0047: endfinally - IL_0048: ldnull - IL_0049: pop - IL_004a: endfinally + """ + .method public static void test() cil managed + { + + .maxstack 3 + .locals init (valuetype System.Span`1 V_0, + class [runtime]System.Collections.IEnumerator V_1, + class [runtime]System.IDisposable V_2) + IL_0000: call !!0[] [runtime]System.Array::Empty() + IL_0005: newobj instance void valuetype System.Span`1::.ctor(!0[]) + IL_000a: stloc.0 + IL_000b: ldloc.0 + IL_000c: box valuetype System.Span`1 + IL_0011: unbox.any [runtime]System.Collections.IEnumerable + IL_0016: callvirt instance class [runtime]System.Collections.IEnumerator [runtime]System.Collections.IEnumerable::GetEnumerator() + IL_001b: stloc.1 + .try + { + IL_001c: ldloc.1 + IL_001d: callvirt instance bool [runtime]System.Collections.IEnumerator::MoveNext() + IL_0022: brfalse.s IL_0031 + + IL_0024: ldloc.1 + IL_0025: callvirt instance object [runtime]System.Collections.IEnumerator::get_Current() + IL_002a: call void [runtime]System.Console::WriteLine(object) + IL_002f: br.s IL_001c + + IL_0031: leave.s IL_0045 + + } + finally + { + IL_0033: ldloc.1 + IL_0034: isinst [runtime]System.IDisposable + IL_0039: stloc.2 + IL_003a: ldloc.2 + IL_003b: brfalse.s IL_0044 + + IL_003d: ldloc.2 + IL_003e: callvirt instance void [runtime]System.IDisposable::Dispose() + IL_0043: endfinally + IL_0044: endfinally + } + IL_0045: ret + } + } - IL_004b: ldloc.2 - IL_004c: pop - IL_004d: ret - }""" +""" ]) [] diff --git a/tests/fsharp/FSharpSuite.Tests.fsproj b/tests/fsharp/FSharpSuite.Tests.fsproj index 533bc765dc3..79fdc521ea7 100644 --- a/tests/fsharp/FSharpSuite.Tests.fsproj +++ b/tests/fsharp/FSharpSuite.Tests.fsproj @@ -11,7 +11,7 @@ true false false - $(OtherFlags) --warnon:1182 + $(OtherFlags) --warnon:1182 --langversion:preview nunit 3186 @@ -28,11 +28,14 @@ + + + diff --git a/tests/fsharp/core/seq/test.fsx b/tests/fsharp/core/seq/test.fsx index 14f71eb2940..107f79676d1 100644 --- a/tests/fsharp/core/seq/test.fsx +++ b/tests/fsharp/core/seq/test.fsx @@ -729,7 +729,33 @@ module TestCollectOnStructSeq = seq { yield! Seq.collect (fun _ -> x) [1] } check "ccekecnwe" (iterate (Unchecked.defaultof) |> Seq.length) 2 - + +module CheckStateMachineCompilationOfMatchBindingVariables = + let f xs = + seq { + match xs with + | 1,h + | h,1 -> + let stackTrace = new System.Diagnostics.StackTrace() + let methodBase = stackTrace.GetFrame(1).GetMethod() + System.Console.WriteLine(methodBase.Name) + // This checks we have a state machine. In the combinator compilation + // we get 'Invoke'. + check "vwehoehwvo" methodBase.Name "MoveNextImpl" + yield h + yield h + | 2,h + | h,2 -> + yield h + | _ -> () + } + + check "ccekecnwevwe1" (f (1, 2) |> Seq.toList) [2;2] + check "ccekecnwevwe2" (f (2, 1) |> Seq.toList) [2;2] + check "ccekecnwevwe3" (f (2, 3) |> Seq.toList) [3] + check "ccekecnwevwe4" (f (3, 2) |> Seq.toList) [3] + check "ccekecnwevwe5" (f (3, 3) |> Seq.toList) [] + (*--------------------------------------------------------------------------- !* wrap up *--------------------------------------------------------------------------- *) diff --git a/tests/fsharp/core/state-machines/neg-resumable-01.bsl b/tests/fsharp/core/state-machines/neg-resumable-01.bsl new file mode 100644 index 00000000000..a41e25ac3f5 --- /dev/null +++ b/tests/fsharp/core/state-machines/neg-resumable-01.bsl @@ -0,0 +1,18 @@ + +neg-resumable-01.fsx(62,17,63,37): typecheck error FS3501: Invalid resumable code. A 'let rec' occured in the resumable code specification + +neg-resumable-01.fsx(70,9,70,19): typecheck error FS3402: The construct '__resumeAt' may only be used in valid resumable code. + +neg-resumable-01.fsx(75,42,75,54): typecheck error FS3402: The construct '__resumeAt' may only be used in valid resumable code. + +neg-resumable-01.fsx(83,21,83,31): typecheck error FS3402: The construct '__resumeAt' may only be used in valid resumable code. + +neg-resumable-01.fsx(92,23,92,41): typecheck error FS3402: The construct '__resumableEntry' may only be used in valid resumable code. + +neg-resumable-01.fsx(104,31,104,47): typecheck error FS3402: The construct '__resumableEntry' may only be used in valid resumable code. + +neg-resumable-01.fsx(106,29,106,39): typecheck error FS3402: The construct '__resumeAt' may only be used in valid resumable code. + +neg-resumable-01.fsx(122,31,122,47): typecheck error FS3402: The construct '__resumableEntry' may only be used in valid resumable code. + +neg-resumable-01.fsx(144,31,144,47): typecheck error FS3402: The construct '__resumableEntry' may only be used in valid resumable code. diff --git a/tests/fsharp/core/state-machines/neg-resumable-01.fsx b/tests/fsharp/core/state-machines/neg-resumable-01.fsx new file mode 100644 index 00000000000..ae41702953d --- /dev/null +++ b/tests/fsharp/core/state-machines/neg-resumable-01.fsx @@ -0,0 +1,152 @@ +module Tests_Tasks + +#nowarn "57" // experimental +#nowarn "3513" // resumable code invocation +open FSharp.Core.CompilerServices +open FSharp.Core.CompilerServices.StateMachineHelpers +open System.Runtime.CompilerServices + +//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// No warnings expected in the declarations + +module ``No warning for resumable code that is just a simple expression`` = + + let inline f1 () = ResumableCode(fun sm -> true ) + +module ``No warning for resumable code that is just a sequential expression`` = + + + let inline f1 () = + ResumableCode(fun sm -> + printfn "hello" + true) + +module ``No warning for protected use of __resumeAt`` = + + + let inline f1 () = + ResumableCode(fun sm -> + if __useResumableCode then + __resumeAt 0 // we don't get a warning here + true + else + false ) + +module ``No warning for protected use of __resumableEntry`` = + + + let inline f1 () = + ResumableCode(fun sm -> + if __useResumableCode then + match __resumableEntry() with + | Some contID -> true + | None -> true + else + false) + +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// No warnings expected in code before this line + + +let inline MoveNext(x: byref<'T> when 'T :> IAsyncStateMachine) = x.MoveNext() +let inline MoveOnce(x: byref<'T> when 'T :> IAsyncStateMachine and 'T :> IResumableStateMachine<'Data>) = + MoveNext(&x) + x.Data + +// Resumable code may not have let rec statements +module ``Error on let rec in resumable code`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + + let rec f x = if x > 0 then f (x-1) else inputValue + 13 + f 10 + f 2 |> ignore + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + +module ``Error on unprotected __resumeAt`` = + let inline f1 () = + __resumeAt 0 + 1 + +module ``Error on unprotected __resumeAt in resumable code`` = + let inline f1 () = + ResumableCode(fun sm -> __resumeAt 0) + +module ``Error because fast integer for loop doesn't supported resumable code`` = + + let inline f1 () = + ResumableCode(fun sm -> + if __useResumableCode then + for i = 0 to 1 do + __resumeAt 0 // we expect an error here - this is not valid resumable code + true + else + false) + +module ``Error because unprotected __resumableEntry`` = + + let inline f1 () = + ResumableCode(fun sm -> + match __resumableEntry() with // we expect an error here - this is not valid resumable code without 'if .. ' + | Some contID -> false + | None -> true + ) + +module ``let bound function can't use resumable code constructs`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + + __resumeAt 1 + let f () = + match __resumableEntry() with // we expect an error here - this is not in resumable code + | Some contID -> + __resumeAt contID + | None -> + 20+inputValue + f() |> ignore + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + +module ``Check no resumption point in try-finally `` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + __resumeAt 1 + let mutable res = inputValue + try + // Attempt to specify a resumption point in the try-finally + match __resumableEntry() with // we expect an error here - this is not in resumable code + | Some contID -> + failwith "unreachable" + res <- 0 + | None -> + res <- res + 10 + finally + res <- res + 20 + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + +module ``Check no resumption point in fast integer for loop`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + __resumeAt 1 + let mutable res = inputValue + let mutable count = 0 + for i = 0 to 9 do + // Attempt to specify a resumption point in the for loop. THis is not permitted + // and while loops should be used instead + match __resumableEntry() with // we expect an error here - this is not in resumable code + | Some contID -> + failwith "unreachable" + res <- 0 + | None -> + res <- res + 10 + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) diff --git a/tests/fsharp/core/state-machines/neg-resumable-02.bsl b/tests/fsharp/core/state-machines/neg-resumable-02.bsl new file mode 100644 index 00000000000..6ca06f293de --- /dev/null +++ b/tests/fsharp/core/state-machines/neg-resumable-02.bsl @@ -0,0 +1,6 @@ + +neg-resumable-02.fsx(22,9,32,54): ilxgen error FS3512: This state machine is not statically compilable and no alternative is available. A 'let rec' occured in the resumable code specification. Use an 'if __useResumableCode then else ' to give an alternative. + +neg-resumable-02.fsx(41,9,54,14): ilxgen error FS3511: This state machine is not statically compilable. A 'let rec' occured in the resumable code specification. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. + +neg-resumable-02.fsx(75,9,75,13): ilxgen error FS3511: This state machine is not statically compilable. A 'let rec' occured in the resumable code specification. An alternative dynamic implementation will be used, which may be slower. Consider adjusting your code to ensure this state machine is statically compilable, or else suppress this warning. diff --git a/tests/fsharp/core/state-machines/neg-resumable-02.fsx b/tests/fsharp/core/state-machines/neg-resumable-02.fsx new file mode 100644 index 00000000000..91fed86d501 --- /dev/null +++ b/tests/fsharp/core/state-machines/neg-resumable-02.fsx @@ -0,0 +1,79 @@ +module Tests_Tasks + +#nowarn "57" +open FSharp.Core.CompilerServices +open FSharp.Core.CompilerServices.StateMachineHelpers +open System.Threading.Tasks +open System.Runtime.CompilerServices + +//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// No warnings expected in the declarations + +let inline MoveNext(x: byref<'T> when 'T :> IAsyncStateMachine) = x.MoveNext() +let inline MoveOnce(x: byref<'T> when 'T :> IAsyncStateMachine and 'T :> IResumableStateMachine<'Data>) = + MoveNext(&x) + x.Data + +module ``late compilation error on user-defined let rec in resumable code`` = + + let inline f1 (code: unit -> ResumableCode<_,_>) = ResumableCode(fun sm -> code().Invoke(&sm)) + + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + let __stack_step = + f1(fun () -> + let rec f x = f x + 1 // resumable code can't be used because of 'let rec' and no alternative is given + f 3 |> ignore + ResumableCode.Zero()).Invoke(&sm) + () + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + makeStateMachine 4 + +module ``compilation warning on user-defined let rec in resumable code when alternative given`` = + + let inline f1 (code: unit -> ResumableCode<_,_>) = ResumableCode(fun sm -> code().Invoke(&sm)) + + let makeStateMachine () = + if __useResumableCode then + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + let __stack_step = + f1(fun () -> + let rec f x = f x + 1 // resumable code can't be used because of 'let rec' and no alternative is given + f 3 |> ignore + ResumableCode.Zero()).Invoke(&sm) + () + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + else + 2 + + + makeStateMachine () + +module ``no compilation warning on user-defined let in task`` = + + let makeTask () = + task { + let f x = + printfn "ewcvw" + printfn "ewcvw" + printfn "ewcvw" + printfn "ewcvw" + 1 + return f 1 + } + +module ``compilation warning on user-defined let rec in task`` = + + let makeTask () = + task { + let rec f x = f x + 1 + return f 1 + } + diff --git a/tests/fsharp/core/state-machines/test.fsx b/tests/fsharp/core/state-machines/test.fsx new file mode 100644 index 00000000000..6139f25053b --- /dev/null +++ b/tests/fsharp/core/state-machines/test.fsx @@ -0,0 +1,672 @@ +module Tests_Tasks + +#nowarn "57" +open FSharp.Core.CompilerServices +open FSharp.Core.CompilerServices.StateMachineHelpers +open System.Runtime.CompilerServices +open System.Threading.Tasks + + +let failures = ref [] + +let report_failure (s : string) = + stderr.Write" NO: " + stderr.WriteLine s + failures := !failures @ [s] + +let test s b = + stderr.Write(s:string) + if b then stderr.WriteLine " OK" else report_failure s + stderr.WriteLine "" + +let check s v1 v2 = + stderr.Write(s:string); + if (v1 = v2) then + stderr.WriteLine " OK" + stderr.WriteLine "" + else + eprintf " FAILED: got %A, expected %A" v1 v2 + stderr.WriteLine "" + report_failure s + +let inline MoveNext(x: byref<'T> when 'T :> IAsyncStateMachine) = x.MoveNext() +let inline MoveOnce(x: byref<'T> when 'T :> IAsyncStateMachine and 'T :> IResumableStateMachine<'Data>) = + MoveNext(&x) + x.Data + +module ``Check simple state machine`` = + let makeStateMachine() = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + sm.Data <- 1 // we expect this result for successful resumable code compilation + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + check "ResumableObject_SimpleImmediateExpression" (makeStateMachine()) 1 + + +module ``Check resumable code can capture variables`` = + let makeStateMachine x = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + sm.Data <- 1 + x // we expect this result for successful resumable code compilation + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + let sm3 = makeStateMachine 3 + check "vwervwkhevh" (makeStateMachine 3) 4 + + +module ``Check resumable code may be preceeded by value definitions`` = + let makeStateMachine x = + let rnd = System.Random().Next(4) + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + sm.Data <- x + rnd - rnd // we expect this result for successful resumable code compilation + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + check "cvwvweewvhjkv" (makeStateMachine 4) 4 + +module ``Check resumable code may contain local function definitions`` = + let makeStateMachine y = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + let someFunction x = x + 1 + sm.Data <- someFunction y + someFunction y + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + check "vewwevbrklbre" (makeStateMachine 3) 8 + +module ``Check resumable code may be preceeded by function definitions`` = + let makeStateMachine y = + let someFunction1 x = x + 1 + let someFunction2 x = someFunction1 x + 2 + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + sm.Data <- someFunction2 y + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + check "vwekvewkhvew" (makeStateMachine 3) 6 + +module ``Check resumable code may contain let statements without resumption points`` = + let makeStateMachine x = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + let y = 1 - x + if x > 3 then + sm.Data <- 1 + x + else + sm.Data <- y + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + check "vwelvewl" (makeStateMachine 3) -2 + +module ``Check resumable code may contain sequential statements without resumption points`` = + let makeStateMachine y = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + printfn "step1" + sm.Data <- y + 2 + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + check "ewvkwekvwevwvek" (makeStateMachine 3) 5 + +module ``Check resuming at start of method`` = + let makeStateMachine y = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + + if __useResumableCode then + __resumeAt 0 + let __stack_fin = ResumableCode.Yield().Invoke(&sm) // label 1 + if __stack_fin then + sm.Data <- 20+y + else + sm.Data <- 10+y // we should end up here + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + check "vwrvwlkelwe" (makeStateMachine 3) 13 + +module ``Check resuming at drop through`` = + let makeStateMachine y = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + __resumeAt 100 + let __stack_fin = ResumableCode.Yield().Invoke(&sm) // label 1 + if __stack_fin then + sm.Data <- 20+y + else + sm.Data <- 10+y // we should end up here + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + check "cvqelekckeq" (makeStateMachine 3) 13 + +module ``Check resuming at a resumption point`` = + let makeStateMachine y = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + + if __useResumableCode then + __resumeAt 1 + let __stack_fin = ResumableCode.Yield().Invoke(&sm) // label 1 + if __stack_fin then + sm.Data <- 20+y // we should end up here + else + sm.Data <- 10+y + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + check "vwlvkjlewjwevj" (makeStateMachine 3) 23 + + +module ``Check resumable code may contain try-with without resumption points`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + + if __useResumableCode then + try + sm.Data <- inputValue + 10 + with e -> + sm.Data <- 12 + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "fvwewejkhkwe" (makeStateMachine 13) 23 + +module ``Check resuming at resumption point in try block`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + __resumeAt 1 // this goes straight to label 1 + try + failwith "unreachable #1" // this is skipped because we jump straight to label 1 + let __stack_fin = ResumableCode.Yield().Invoke(&sm) // label 1 is resumption of this + if __stack_fin then + // This is the resumption path + sm.Data <- 20+inputValue // this is the result + else + // This is the suspension path. It is not executed in this test because we jump straight to label 1 + failwith "unreachable #2" + with e -> + sm.Data <- 12 + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "ResumableCode_TryWithResumption" (makeStateMachine 13) 33 + +module ``Check exception thrown in try block after resumption is caught`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + __resumeAt 1 // this goes straight to label 1 + try + // Specify a resumption point + let __stack_fin = ResumableCode.Yield().Invoke(&sm) // label 1 is resumption of this + if not __stack_fin then + // This is the suspension path. It is not executed in this test because we jump straight to label 1 + sm.Data <- 10+inputValue + else + // This is the resumption path + failwith "raise" + sm.Data <- inputValue + 15 + with e -> + sm.Data <- inputValue + 12 // this is the result + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "ResumableCode_TryWithResumptionException" (makeStateMachine 13) 25 + +module ``Check exception thrown in try block with no resumption points is caught`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + try + failwith "fail" + with e -> + sm.Data <- inputValue + 12 + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "ResumableCode_TryWithExceptionNoResumption" (makeStateMachine 13) 25 + +module ``Check resumable code may contain try-finally without resumption points`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + let mutable res = 0 + try + res <- inputValue + 10 + finally + res <- inputValue + 40 + sm.Data <- res + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "ResumableCode_TryFinallyNoResumption" (makeStateMachine 13) 53 + +// try-finally may **not** contain resumption points. This is because it's +// very difficult to codegen them in IL. Instead you have to code try/finally logic as shown below. +// See also tasks.fs. +module ``Check can simulate try-finally via try-with`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + __resumeAt 1 // this goes straight to label 1 + let mutable res = 0 // note, this initialization doesn't actually happen since we go straight to label 1. However this is the zero-init value. + let mutable __stack_completed = false // note, this initialization doesn't actually happen since we go straight to label 1. However this is the zero-init value. + try + failwith "unreachable" // this code is not executed as the __resumeAt goes straight to resumption label 1 + + // Specify a resumption point + let __stack_fin = ResumableCode.Yield().Invoke(&sm) + if not __stack_fin then + // This is the suspension path. It is not executed in this test because we jump straight to label 1 + failwith "unreachable" + res <- 0 + __stack_completed <- false + else + // This is the resumption path + // Label 1 goes here + res <- res + + inputValue + 10 // this gets executed and contributes to the result + __stack_completed <- true + with _ -> + res <- res + 20 + reraise() + if __stack_completed then + res <- res + 20 + sm.Data <- res + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "vwevewewlvjve" (makeStateMachine 13) 43 + +module ``Check resumable code may contain try-finally without resumption points and raising exception`` = + let mutable res = 0 + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + try + failwith "fail" + finally + res <- inputValue + 10 + sm.Data <- res + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "cvwekjwejkl" (try makeStateMachine 13 with _ -> res ) 23 + +module ``Check resumable code may contain while loop without resumption`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + let mutable count = 0 + while count < 10 do + count <- count + 1 + sm.Data <- inputValue + 12 + count + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "fvewhjkvekwhk" (makeStateMachine 13) 35 + +module ``Check resumable code may contain while loop with resumption`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + __resumeAt 1 // this goes straight to label 1 + let mutable count = 0 // note, this initialization doesn't actually happen since we go straight to label 1. However this is the zero-init value. + let mutable res = 0 // note, this initialization doesn't actually happen since we go straight to label 1. However this is the zero-init value. + while count < 10 do + // Specify a resumption point in the loop + let __stack_fin = ResumableCode.Yield().Invoke(&sm) + if not __stack_fin then + // This is the suspension path. It is executed in this test for subsequent iterations in this loop + count <- count + 1 + res <- res + 20 // gets executed 9 times + else + // This is the resumption path + // Label 1 goes here + count <- count + 1 + res <- res + 10 // gets executed once + // res ends up as 190 + sm.Data <- inputValue + res + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "wejlcewjllkjwce" (makeStateMachine 13) 203 + + +module ``Check resumable code may contain integer for loop without resumption`` = + let makeStateMachine inputValue = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + let mutable count = 0 + for i = 0 to 9 do + count <- count + 1 + sm.Data <- inputValue + 12 + count + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "celjkcwljeljwecl" (makeStateMachine 13) 35 + +module ``Check resumable code can contain a conditional with a resumption point`` = + let makeStateMachine y = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + __resumeAt 1 + failwith "fail" + if y > 10 then + let __stack_fin = ResumableCode.Yield().Invoke(&sm) + if not __stack_fin then + // This is the suspension path. It is not executed in this test as we go straight to label 1 + failwith "fail" + else + // This is the resumption path + // Label 1 goes here + sm.Data <- 20+y // this is the answer + else + sm.Data <- 30 + y + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "vewowevewoi" (makeStateMachine 13) 33 + +module ``Check resumable code can contain a conditional with a resumption point in else branch`` = + let makeStateMachine y = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + __resumeAt 1 + failwith "fail" + if y <= 10 then + sm.Data <- 30 + y + else + let __stack_fin = ResumableCode.Yield().Invoke(&sm) + if not __stack_fin then + // This is the suspension path. It is not executed in this test as we go straight to label 1 + failwith "fail" + else + // This is the resumption path + // Label 1 goes here + sm.Data <- 20+y // this is the answer + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun sm -> MoveOnce(&sm))) + + check "vewowevewoi" (makeStateMachine 13) 33 + + + +let inline checkStateMachine nm = + check nm (System.Reflection.MethodBase.GetCurrentMethod().Name) "MoveNext" + +// The main tests for tasks are in tests\FSharp.Core.UnitTests\FSharp.Core\Microsoft.FSharp.Control\Tasks.fs +// These simply detect state machine compilation +module ``Check simple task compiles to state machine`` = + + let test1() = + + task { + checkStateMachine "vevroerhn11" + return 1 + } + + test1().Wait() + +module ``Check simple task with bind compiles to state machine`` = + let test2() = + + task { + checkStateMachine "vevroerhn12" + let! v1 = Task.FromResult 1 + checkStateMachine "vevroerhn13" + return 1 + } + + test2().Wait() + + +module ``Check task with multiple bind doesn't cause code explosion from inlining and compiles to state machine`` = + + let syncTask() = Task.FromResult 100 + + let tenBindSync_Task() = + task { + let! res1 = syncTask() + checkStateMachine "vevroerhn121" + let! res2 = syncTask() + checkStateMachine "vevroerhn122" + let! res3 = syncTask() + checkStateMachine "vevroerhn123" + let! res4 = syncTask() + checkStateMachine "vevroerhn124" + let! res5 = syncTask() + checkStateMachine "vevroerhn125" + let! res6 = syncTask() + checkStateMachine "vevroerhn126" + let! res7 = syncTask() + checkStateMachine "vevroerhn127" + let! res8 = syncTask() + checkStateMachine "vevroerhn128" + let! res9 = syncTask() + checkStateMachine "vevroerhn129" + let! res10 = syncTask() + checkStateMachine "vevroerhn120" + return res1 + res2 + res3 + res4 + res5 + res6 + res7 + res8 + res9 + res10 + } + + tenBindSync_Task().Wait() + +module ``Check task with try with compiles to state machine`` = + let t67() = + task { + checkStateMachine "vevroerhn180" + try + checkStateMachine "vevroerhn181" + do! Task.Delay(0) + checkStateMachine "vevroerhn182" + with + | :? System.ArgumentException -> + () + | _ -> + () + } + + t67().Wait() + +module ``Check task with try with and incomplete match compiles to state machine`` = + let t68() = + task { + try + checkStateMachine "vevroerhn190" + do! Task.Delay(0) + checkStateMachine "vevroerhn191" + with + | :? System.ArgumentException -> + () + } + + t68().Wait() + +module ``Check task with while loop with resumption points compiles to state machine`` = + let t68() : Task = + task { + checkStateMachine "vevroerhn200" + let mutable i = 0 + while i < 1 do + checkStateMachine "vevroerhn201" + i <- i + 1 + do! Task.Yield() + () + checkStateMachine "vevroerhn202" + return i + } + + t68().Wait() + +module ``Check task with try finally compiles to state machine`` = + let t68() = + task { + let mutable ran = false + try + checkStateMachine "vevroerhn210" + do! Task.Delay(100) + checkStateMachine "vevroerhn211" + + finally + ran <- true + return ran + } + + t68().Wait() + +module ``Check task with use compiles to state machine`` = + let t68() = + task { + let mutable disposed = false + use d = { new System.IDisposable with member __.Dispose() = disposed <- true } + checkStateMachine "vevroerhn221" + do! Task.Delay(100) + checkStateMachine "vevroerhn221" + } + + t68().Wait() + +module ``Check nested task compiles to state machine`` = + let t68() = + task { + let mutable n = 0 + checkStateMachine "vevroerhn230" + while n < 10 do + let! _ = + task { + do! Task.Yield() + checkStateMachine "vevroerhn231" + let! _ = Task.FromResult(0) + n <- n + 1 + } + n <- n + 1 + } + + t68().Wait() + +module ``Check after code may include closures`` = + let makeStateMachine x = + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + if __useResumableCode then + let y = 1 - x + if x > 3 then + sm.Data <- 1 + x + else + sm.Data <- y + else + sm.Data <- 0xdeadbeef // if we get this result it means we've failed to compile as resumable code + )) + (SetStateMachineMethodImpl<_>(fun sm state -> ())) + (AfterCode<_,_>(fun smref -> + let sm = smref // deref the byref so we can rvalue copy-capture the state machine + let f (x:int ) = + printfn "large closure" + printfn "large closure" + printfn "large closure" + printfn "large closure" + let mutable sm = sm + MoveOnce(&sm) + f 3)) + check "vwelvewl" (makeStateMachine 3) -2 + +#if TESTS_AS_APP +let RUN() = !failures +#else +let aa = + match !failures with + | [] -> + stdout.WriteLine "Test Passed" + System.IO.File.WriteAllText("test.ok","ok") + exit 0 + | _ -> + stdout.WriteLine "Test Failed" + exit 1 +#endif + diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index a86071426d8..2a45b917abb 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -461,6 +461,45 @@ module CoreTests = testOkFile.CheckExists() + [] + let ``state-machines-non-optimized`` () = + let cfg = testConfig "core/state-machines" + + use testOkFile = fileguard cfg "test.ok" + + fsc cfg "%s -o:test.exe -g --tailcalls- --optimize- --langversion:preview" cfg.fsc_flags ["test.fsx"] + + peverify cfg "test.exe" + + exec cfg ("." ++ "test.exe") "" + + testOkFile.CheckExists() + + [] + let ``state-machines-optimized`` () = + let cfg = testConfig "core/state-machines" + + use testOkFile = fileguard cfg "test.ok" + + fsc cfg "%s -o:test.exe -g --tailcalls+ --optimize+ --langversion:preview" cfg.fsc_flags ["test.fsx"] + + peverify cfg "test.exe" + + exec cfg ("." ++ "test.exe") "" + + testOkFile.CheckExists() + + [] + let ``state-machines neg-resumable-01`` () = + let cfg = testConfig "core/state-machines" + singleVersionedNegTest cfg "preview" "neg-resumable-01" + + + [] + let ``state-machines neg-resumable-02`` () = + let cfg = testConfig "core/state-machines" + singleVersionedNegTest cfg "preview" "neg-resumable-02" + [] let ``lots-of-conditionals``() = let cfg = testConfig "core/large/conditionals" diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember01.il.bsl index b07afd62275..cd87bf2f64a 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember01.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000780 Length: 0x00000227 } .module CCtorDUWithMember01.exe -// MVID: {60B68B7E-26F1-14EE-A745-03837E8BB660} +// MVID: {60BD4554-26F1-14EE-A745-03835445BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06D80000 +// Image base: 0x04E50000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,36 +63,24 @@ .method public static void main@() cil managed { .entrypoint - // Code size 61 (0x3d) - .maxstack 4 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_0, - [1] class CCtorDUWithMember01a/C V_1, - [2] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_2, - [3] class CCtorDUWithMember01a/C V_3) + // Code size 53 (0x35) + .maxstack 8 .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' .line 2,2 : 1,23 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\CCtorDUWithMember\\CCtorDUWithMember01.fs' IL_0000: ldstr "File1.A = %A" IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class CCtorDUWithMember01a/C>::.ctor(string) IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_000f: stloc.0 - IL_0010: call class CCtorDUWithMember01a/C CCtorDUWithMember01a/C::get_A() - IL_0015: stloc.1 - IL_0016: ldloc.0 - IL_0017: ldloc.1 - IL_0018: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_001d: pop + IL_000f: call class CCtorDUWithMember01a/C CCtorDUWithMember01a/C::get_A() + IL_0014: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0019: pop .line 3,3 : 1,23 '' - IL_001e: ldstr "Test.e2 = %A" - IL_0023: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class CCtorDUWithMember01a/C>::.ctor(string) - IL_0028: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_002d: stloc.2 - IL_002e: call class CCtorDUWithMember01a/C CCtorDUWithMember01a::get_e2() - IL_0033: stloc.3 - IL_0034: ldloc.2 - IL_0035: ldloc.3 - IL_0036: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_003b: pop - IL_003c: ret + IL_001a: ldstr "Test.e2 = %A" + IL_001f: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class CCtorDUWithMember01a/C>::.ctor(string) + IL_0024: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0029: call class CCtorDUWithMember01a/C CCtorDUWithMember01a::get_e2() + IL_002e: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0033: pop + IL_0034: ret } // end of method $CCtorDUWithMember01::main@ } // end of class ''.$CCtorDUWithMember01 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember02.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember02.il.bsl index 10cb539ef09..c9441f898d1 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember02.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember02.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000308 Length: 0x000000E4 } .module CCtorDUWithMember02.exe -// MVID: {60B68B7E-D176-C99D-A745-03837E8BB660} +// MVID: {608C04FF-D176-C99D-A745-0383FF048C60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06BF0000 +// Image base: 0x06EF0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,23 +63,17 @@ .method public static void main@() cil managed { .entrypoint - // Code size 31 (0x1f) - .maxstack 4 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_0, - [1] int32 V_1) + // Code size 27 (0x1b) + .maxstack 8 .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' .line 2,2 : 1,17 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\CCtorDUWithMember\\CCtorDUWithMember02.fs' IL_0000: ldstr "x = %A" IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_000f: stloc.0 - IL_0010: call int32 CCtorDUWithMember02a::get_y() - IL_0015: stloc.1 - IL_0016: ldloc.0 - IL_0017: ldloc.1 - IL_0018: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_001d: pop - IL_001e: ret + IL_000f: call int32 CCtorDUWithMember02a::get_y() + IL_0014: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0019: pop + IL_001a: ret } // end of method $CCtorDUWithMember02::main@ } // end of class ''.$CCtorDUWithMember02 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember03.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember03.il.bsl index 6f45553c0ec..3f429b894ad 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember03.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember03.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000298 Length: 0x000000B2 } .module CCtorDUWithMember03.exe -// MVID: {60B68B7E-C97B-D207-A745-03837E8BB660} +// MVID: {608C04FF-C97B-D207-A745-0383FF048C60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x05970000 +// Image base: 0x072C0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,23 +63,17 @@ .method public static void main@() cil managed { .entrypoint - // Code size 31 (0x1f) - .maxstack 4 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_0, - [1] int32 V_1) + // Code size 27 (0x1b) + .maxstack 8 .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' .line 2,2 : 1,23 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\CCtorDUWithMember\\CCtorDUWithMember03.fs' IL_0000: ldstr "File1.x = %A" IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_000f: stloc.0 - IL_0010: call int32 CCtorDUWithMember03a::get_x() - IL_0015: stloc.1 - IL_0016: ldloc.0 - IL_0017: ldloc.1 - IL_0018: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_001d: pop - IL_001e: ret + IL_000f: call int32 CCtorDUWithMember03a::get_x() + IL_0014: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0019: pop + IL_001a: ret } // end of method $CCtorDUWithMember03::main@ } // end of class ''.$CCtorDUWithMember03 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember04.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember04.il.bsl index 0813094fef6..41590465474 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember04.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/CCtorDUWithMember/CCtorDUWithMember04.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000298 Length: 0x000000B2 } .module CCtorDUWithMember04.exe -// MVID: {60B68B7E-CF28-717B-A745-03837E8BB660} +// MVID: {608C04FF-CF28-717B-A745-0383FF048C60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x07050000 +// Image base: 0x06780000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,23 +63,17 @@ .method public static void main@() cil managed { .entrypoint - // Code size 31 (0x1f) - .maxstack 4 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_0, - [1] int32 V_1) + // Code size 27 (0x1b) + .maxstack 8 .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' .line 2,2 : 1,23 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\CCtorDUWithMember\\CCtorDUWithMember04.fs' IL_0000: ldstr "File1.x = %A" IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) IL_000a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_000f: stloc.0 - IL_0010: call int32 CCtorDUWithMember04a::get_x() - IL_0015: stloc.1 - IL_0016: ldloc.0 - IL_0017: ldloc.1 - IL_0018: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_001d: pop - IL_001e: ret + IL_000f: call int32 CCtorDUWithMember04a::get_x() + IL_0014: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0019: pop + IL_001a: ret } // end of method $CCtorDUWithMember04::main@ } // end of class ''.$CCtorDUWithMember04 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter01.il.bsl index 91a0b81b6ca..f8f111fcb2b 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter01.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x000001F8 Length: 0x0000007A } .module GenIter01.exe -// MVID: {60B78A57-F836-DC98-A745-0383578AB760} +// MVID: {60BCDCE8-F836-DC98-A745-0383E8DCBC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x04D30000 +// Image base: 0x055E0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -54,7 +54,7 @@ .method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 squaresOfOneToTen() cil managed { - // Code size 82 (0x52) + // Code size 78 (0x4e) .maxstack 5 .locals init ([0] valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1 V_0, [1] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_1, @@ -94,7 +94,7 @@ IL_002b: ldnull IL_002c: stloc.2 - IL_002d: leave.s IL_0048 + IL_002d: leave.s IL_0044 .line 5,6 : 7,23 '' } // end .try @@ -104,26 +104,22 @@ IL_0030: isinst [mscorlib]System.IDisposable IL_0035: stloc.s V_4 IL_0037: ldloc.s V_4 - IL_0039: brfalse.s IL_0045 + IL_0039: brfalse.s IL_0043 .line 100001,100001 : 0,0 '' IL_003b: ldloc.s V_4 IL_003d: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_0042: ldnull - IL_0043: pop - IL_0044: endfinally + IL_0042: endfinally .line 100001,100001 : 0,0 '' - IL_0045: ldnull - IL_0046: pop - IL_0047: endfinally + IL_0043: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_0048: ldloc.2 - IL_0049: pop + IL_0044: ldloc.2 + IL_0045: pop .line 5,6 : 5,25 '' - IL_004a: ldloca.s V_0 - IL_004c: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() - IL_0051: ret + IL_0046: ldloca.s V_0 + IL_0048: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() + IL_004d: ret } // end of method GenIter01::squaresOfOneToTen } // end of class GenIter01 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter02.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter02.il.bsl index e9ec641157f..985b1b8950d 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter02.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter02.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x000001F8 Length: 0x0000007B } .module GenIter02.exe -// MVID: {60B78A57-F857-DC98-A745-0383578AB760} +// MVID: {60BCDCE8-F857-DC98-A745-0383E8DCBC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x066F0000 +// Image base: 0x07230000 // =============== CLASS MEMBERS DECLARATION =================== @@ -54,7 +54,7 @@ .method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 squaresOfOneToTenB() cil managed { - // Code size 98 (0x62) + // Code size 94 (0x5e) .maxstack 5 .locals init ([0] valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1 V_0, [1] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_1, @@ -99,7 +99,7 @@ IL_003b: ldnull IL_003c: stloc.2 - IL_003d: leave.s IL_0058 + IL_003d: leave.s IL_0054 .line 5,7 : 7,23 '' } // end .try @@ -109,26 +109,22 @@ IL_0040: isinst [mscorlib]System.IDisposable IL_0045: stloc.s V_4 IL_0047: ldloc.s V_4 - IL_0049: brfalse.s IL_0055 + IL_0049: brfalse.s IL_0053 .line 100001,100001 : 0,0 '' IL_004b: ldloc.s V_4 IL_004d: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_0052: ldnull - IL_0053: pop - IL_0054: endfinally + IL_0052: endfinally .line 100001,100001 : 0,0 '' - IL_0055: ldnull - IL_0056: pop - IL_0057: endfinally + IL_0053: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_0058: ldloc.2 - IL_0059: pop + IL_0054: ldloc.2 + IL_0055: pop .line 5,7 : 5,25 '' - IL_005a: ldloca.s V_0 - IL_005c: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() - IL_0061: ret + IL_0056: ldloca.s V_0 + IL_0058: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() + IL_005d: ret } // end of method GenIter02::squaresOfOneToTenB } // end of class GenIter02 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter03.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter03.il.bsl index b649a939686..526a8fbac7b 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter03.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter03.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x000001F8 Length: 0x0000007B } .module GenIter03.exe -// MVID: {60B78A57-F77C-DC98-A745-0383578AB760} +// MVID: {60BCDCE8-F77C-DC98-A745-0383E8DCBC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x057E0000 +// Image base: 0x04BE0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -54,7 +54,7 @@ .method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 squaresOfOneToTenC() cil managed { - // Code size 83 (0x53) + // Code size 79 (0x4f) .maxstack 5 .locals init ([0] valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1 V_0, [1] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_1, @@ -94,7 +94,7 @@ IL_002c: ldnull IL_002d: stloc.2 - IL_002e: leave.s IL_0049 + IL_002e: leave.s IL_0045 .line 4,4 : 30,55 '' } // end .try @@ -104,26 +104,22 @@ IL_0031: isinst [mscorlib]System.IDisposable IL_0036: stloc.s V_4 IL_0038: ldloc.s V_4 - IL_003a: brfalse.s IL_0046 + IL_003a: brfalse.s IL_0044 .line 100001,100001 : 0,0 '' IL_003c: ldloc.s V_4 IL_003e: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_0043: ldnull - IL_0044: pop - IL_0045: endfinally + IL_0043: endfinally .line 100001,100001 : 0,0 '' - IL_0046: ldnull - IL_0047: pop - IL_0048: endfinally + IL_0044: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_0049: ldloc.2 - IL_004a: pop + IL_0045: ldloc.2 + IL_0046: pop .line 4,4 : 28,57 '' - IL_004b: ldloca.s V_0 - IL_004d: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() - IL_0052: ret + IL_0047: ldloca.s V_0 + IL_0049: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() + IL_004e: ret } // end of method GenIter03::squaresOfOneToTenC } // end of class GenIter03 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter04.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter04.il.bsl index c3401ee5341..09d3a9bfd3b 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter04.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/GeneratedIterators/GenIter04.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x000001E8 Length: 0x0000007B } .module GenIter04.exe -// MVID: {60B78A57-F79D-DC98-A745-0383578AB760} +// MVID: {60BCDCE8-F79D-DC98-A745-0383E8DCBC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06F10000 +// Image base: 0x06940000 // =============== CLASS MEMBERS DECLARATION =================== @@ -80,7 +80,7 @@ .method public static void main@() cil managed { .entrypoint - // Code size 93 (0x5d) + // Code size 89 (0x59) .maxstack 5 .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 squaresOfOneToTenD, [1] valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1 V_1, @@ -121,7 +121,7 @@ IL_002f: ldnull IL_0030: stloc.3 - IL_0031: leave.s IL_004c + IL_0031: leave.s IL_0048 .line 4,4 : 28,53 '' } // end .try @@ -131,28 +131,24 @@ IL_0034: isinst [mscorlib]System.IDisposable IL_0039: stloc.s V_5 IL_003b: ldloc.s V_5 - IL_003d: brfalse.s IL_0049 + IL_003d: brfalse.s IL_0047 .line 100001,100001 : 0,0 '' IL_003f: ldloc.s V_5 IL_0041: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_0046: ldnull - IL_0047: pop - IL_0048: endfinally + IL_0046: endfinally .line 100001,100001 : 0,0 '' - IL_0049: ldnull - IL_004a: pop - IL_004b: endfinally + IL_0047: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_004c: ldloc.3 - IL_004d: pop - IL_004e: ldloca.s V_1 - IL_0050: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() - IL_0055: dup - IL_0056: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$GenIter04::squaresOfOneToTenD@4 - IL_005b: stloc.0 - IL_005c: ret + IL_0048: ldloc.3 + IL_0049: pop + IL_004a: ldloca.s V_1 + IL_004c: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() + IL_0051: dup + IL_0052: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$GenIter04::squaresOfOneToTenD@4 + IL_0057: stloc.0 + IL_0058: ret } // end of method $GenIter04::main@ } // end of class ''.$GenIter04 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/ListExpressionStepping/ListExpressionSteppingTest6.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/ListExpressionStepping/ListExpressionSteppingTest6.il.bsl index bfa33913669..3122e29aad1 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/ListExpressionStepping/ListExpressionSteppingTest6.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/ListExpressionStepping/ListExpressionSteppingTest6.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000298 Length: 0x000000BC } .module ListExpressionSteppingTest6.exe -// MVID: {60B78A57-98A2-AB14-A745-0383578AB760} +// MVID: {60BD4553-98A2-AB14-A745-03835345BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06F80000 +// Image base: 0x04EC0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -67,7 +67,7 @@ .method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 f7() cil managed { - // Code size 186 (0xba) + // Code size 178 (0xb2) .maxstack 4 .locals init ([0] valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1 V_0, [1] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_1, @@ -109,7 +109,7 @@ IL_0036: ldnull IL_0037: stloc.2 - IL_0038: leave.s IL_0053 + IL_0038: leave.s IL_004f .line 7,9 : 11,21 '' } // end .try @@ -119,81 +119,73 @@ IL_003b: isinst [mscorlib]System.IDisposable IL_0040: stloc.s V_4 IL_0042: ldloc.s V_4 - IL_0044: brfalse.s IL_0050 + IL_0044: brfalse.s IL_004e .line 100001,100001 : 0,0 '' IL_0046: ldloc.s V_4 IL_0048: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_004d: ldnull - IL_004e: pop - IL_004f: endfinally + IL_004d: endfinally .line 100001,100001 : 0,0 '' - IL_0050: ldnull - IL_0051: pop - IL_0052: endfinally + IL_004e: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_0053: ldloc.2 - IL_0054: pop - IL_0055: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ListExpressionSteppingTest6/ListExpressionSteppingTest6::get_es() - IL_005a: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_005f: stloc.s V_5 + IL_004f: ldloc.2 + IL_0050: pop + IL_0051: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ListExpressionSteppingTest6/ListExpressionSteppingTest6::get_es() + IL_0056: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_005b: stloc.s V_5 .line 10,10 : 11,25 '' .try { - IL_0061: ldloc.s V_5 - IL_0063: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_0068: brfalse.s IL_0090 + IL_005d: ldloc.s V_5 + IL_005f: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() + IL_0064: brfalse.s IL_008c - IL_006a: ldloc.s V_5 - IL_006c: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() - IL_0071: stloc.s V_7 + IL_0066: ldloc.s V_5 + IL_0068: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() + IL_006d: stloc.s V_7 .line 11,11 : 14,31 '' - IL_0073: ldstr "goodbye" - IL_0078: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) - IL_007d: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0082: pop + IL_006f: ldstr "goodbye" + IL_0074: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_0079: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_007e: pop .line 12,12 : 14,21 '' - IL_0083: ldloca.s V_0 - IL_0085: ldloc.s V_7 - IL_0087: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Add(!0) - IL_008c: nop + IL_007f: ldloca.s V_0 + IL_0081: ldloc.s V_7 + IL_0083: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Add(!0) + IL_0088: nop .line 100001,100001 : 0,0 '' - IL_008d: nop - IL_008e: br.s IL_0061 + IL_0089: nop + IL_008a: br.s IL_005d - IL_0090: ldnull - IL_0091: stloc.s V_6 - IL_0093: leave.s IL_00af + IL_008c: ldnull + IL_008d: stloc.s V_6 + IL_008f: leave.s IL_00a7 .line 10,12 : 11,21 '' } // end .try finally { - IL_0095: ldloc.s V_5 - IL_0097: isinst [mscorlib]System.IDisposable - IL_009c: stloc.s V_8 - IL_009e: ldloc.s V_8 - IL_00a0: brfalse.s IL_00ac + IL_0091: ldloc.s V_5 + IL_0093: isinst [mscorlib]System.IDisposable + IL_0098: stloc.s V_8 + IL_009a: ldloc.s V_8 + IL_009c: brfalse.s IL_00a6 .line 100001,100001 : 0,0 '' - IL_00a2: ldloc.s V_8 - IL_00a4: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_00a9: ldnull - IL_00aa: pop - IL_00ab: endfinally + IL_009e: ldloc.s V_8 + IL_00a0: callvirt instance void [mscorlib]System.IDisposable::Dispose() + IL_00a5: endfinally .line 100001,100001 : 0,0 '' - IL_00ac: ldnull - IL_00ad: pop - IL_00ae: endfinally + IL_00a6: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_00af: ldloc.s V_6 - IL_00b1: pop + IL_00a7: ldloc.s V_6 + IL_00a9: pop .line 7,12 : 9,23 '' - IL_00b2: ldloca.s V_0 - IL_00b4: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() - IL_00b9: ret + IL_00aa: ldloca.s V_0 + IL_00ac: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1::Close() + IL_00b1: ret } // end of method ListExpressionSteppingTest6::f7 .property class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop01.il.bsl index 1cbb7d93ca5..c748c706949 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop01.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000140 Length: 0x00000050 } .module ForLoop01.exe -// MVID: {60B68B7F-1795-791C-A745-03837F8BB660} +// MVID: {60BCDCE8-1795-791C-A745-0383E8DCBC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x05340000 +// Image base: 0x070C0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,13 +63,11 @@ .method public static void main@() cil managed { .entrypoint - // Code size 80 (0x50) + // Code size 74 (0x4a) .maxstack 5 .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_0, [1] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_1, - [2] int32 wi, - [3] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_3, - [4] int32 V_4) + [2] int32 wi) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' .line 5,5 : 1,24 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\Misc\\ForLoop01.fs' IL_0000: ldc.i4.1 @@ -89,7 +87,7 @@ IL_001a: ldloc.1 IL_001b: ldnull IL_001c: cgt.un - IL_001e: brfalse.s IL_004f + IL_001e: brfalse.s IL_0049 .line 5,5 : 1,24 '' IL_0020: ldloc.0 @@ -98,23 +96,19 @@ IL_0027: ldstr "%A" IL_002c: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) IL_0031: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0036: stloc.3 - IL_0037: ldloc.2 - IL_0038: stloc.s V_4 - IL_003a: ldloc.3 - IL_003b: ldloc.s V_4 - IL_003d: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0042: pop - IL_0043: ldloc.1 - IL_0044: stloc.0 - IL_0045: ldloc.0 - IL_0046: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() - IL_004b: stloc.1 + IL_0036: ldloc.2 + IL_0037: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_003c: pop + IL_003d: ldloc.1 + IL_003e: stloc.0 + IL_003f: ldloc.0 + IL_0040: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_0045: stloc.1 .line 100001,100001 : 0,0 '' - IL_004c: nop - IL_004d: br.s IL_001a + IL_0046: nop + IL_0047: br.s IL_001a - IL_004f: ret + IL_0049: ret } // end of method $ForLoop01::main@ } // end of class ''.$ForLoop01 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop02.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop02.il.bsl index d40f24fed45..aa69d91fe75 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop02.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop02.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000140 Length: 0x00000050 } .module ForLoop02.exe -// MVID: {60B68B7F-1736-791C-A745-03837F8BB660} +// MVID: {60BCDCE8-1736-791C-A745-0383E8DCBC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x05980000 +// Image base: 0x068C0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,40 +63,34 @@ .method public static void main@() cil managed { .entrypoint - // Code size 41 (0x29) + // Code size 37 (0x25) .maxstack 5 - .locals init ([0] int32 wi, - [1] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_1, - [2] int32 V_2) + .locals init ([0] int32 wi) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' .line 5,5 : 1,19 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\Misc\\ForLoop02.fs' IL_0000: ldc.i4.1 IL_0001: stloc.0 - IL_0002: br.s IL_0022 + IL_0002: br.s IL_001e .line 6,6 : 5,17 '' IL_0004: ldstr "%A" IL_0009: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) IL_000e: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0013: stloc.1 - IL_0014: ldloc.0 - IL_0015: stloc.2 - IL_0016: ldloc.1 - IL_0017: ldloc.2 - IL_0018: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_001d: pop + IL_0013: ldloc.0 + IL_0014: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0019: pop + IL_001a: ldloc.0 + IL_001b: ldc.i4.1 + IL_001c: add + IL_001d: stloc.0 + .line 5,5 : 1,19 '' IL_001e: ldloc.0 IL_001f: ldc.i4.1 - IL_0020: add - IL_0021: stloc.0 - .line 5,5 : 1,19 '' - IL_0022: ldloc.0 - IL_0023: ldc.i4.1 - IL_0024: ldc.i4.3 - IL_0025: add - IL_0026: blt.s IL_0004 + IL_0020: ldc.i4.3 + IL_0021: add + IL_0022: blt.s IL_0004 - IL_0028: ret + IL_0024: ret } // end of method $ForLoop02::main@ } // end of class ''.$ForLoop02 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop03.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop03.il.bsl index 61f328b715c..d1f71df8ed2 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop03.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop03.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000200 Length: 0x0000007B } .module ForLoop03.exe -// MVID: {60B68B7F-1757-791C-A745-03837F8BB660} +// MVID: {60BCDCE8-1757-791C-A745-0383E8DCBC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x07280000 +// Image base: 0x066B0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -62,16 +62,13 @@ .method public static void test1() cil managed { - // Code size 113 (0x71) + // Code size 97 (0x61) .maxstack 5 .locals init ([0] int32 z, [1] int32 i, [2] class [mscorlib]System.Collections.Generic.List`1 V_2, [3] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator V_3, - [4] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_4, - [5] int32 x, - [6] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_6, - [7] int32 V_7) + [4] int32 x) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' .line 10,10 : 4,21 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\Misc\\ForLoop03.fs' IL_0000: ldc.i4.0 @@ -79,7 +76,7 @@ .line 11,11 : 4,28 '' IL_0002: ldc.i4.0 IL_0003: stloc.1 - IL_0004: br.s IL_0048 + IL_0004: br.s IL_0040 .line 12,12 : 6,20 '' IL_0006: call class [mscorlib]System.Collections.Generic.List`1 ForLoop03::get_ra() @@ -106,46 +103,36 @@ IL_0029: nop IL_002a: br.s IL_0013 - IL_002c: ldnull - IL_002d: stloc.s V_4 - IL_002f: leave.s IL_0041 + IL_002c: leave.s IL_003c } // end .try finally { - IL_0031: ldloca.s V_3 - IL_0033: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator - IL_0039: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_003e: ldnull - IL_003f: pop - IL_0040: endfinally + IL_002e: ldloca.s V_3 + IL_0030: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator + IL_0036: callvirt instance void [mscorlib]System.IDisposable::Dispose() + IL_003b: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_0041: ldloc.s V_4 - IL_0043: pop - IL_0044: ldloc.1 - IL_0045: ldc.i4.1 - IL_0046: add - IL_0047: stloc.1 + IL_003c: ldloc.1 + IL_003d: ldc.i4.1 + IL_003e: add + IL_003f: stloc.1 .line 11,11 : 4,28 '' - IL_0048: ldloc.1 - IL_0049: ldc.i4.1 - IL_004a: ldc.i4 0x989680 - IL_004f: add - IL_0050: blt.s IL_0006 + IL_0040: ldloc.1 + IL_0041: ldc.i4.1 + IL_0042: ldc.i4 0x989680 + IL_0047: add + IL_0048: blt.s IL_0006 .line 14,14 : 4,20 '' - IL_0052: ldstr "z = %d" - IL_0057: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) - IL_005c: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0061: stloc.s V_6 - IL_0063: ldloc.0 - IL_0064: stloc.s V_7 - IL_0066: ldloc.s V_6 - IL_0068: ldloc.s V_7 - IL_006a: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_006f: pop - IL_0070: ret + IL_004a: ldstr "z = %d" + IL_004f: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) + IL_0054: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0059: ldloc.0 + IL_005a: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_005f: pop + IL_0060: ret } // end of method ForLoop03::test1 .property class [mscorlib]System.Collections.Generic.List`1 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/Lock01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/Lock01.il.bsl index 2e01e08825f..76b81b98e9c 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/Lock01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/Lock01.il.bsl @@ -41,13 +41,13 @@ // Offset: 0x00000188 Length: 0x00000064 } .module Lock01.exe -// MVID: {60B68B7F-2BCA-B308-A745-03837F8BB660} +// MVID: {60BCDCE8-2BCA-B308-A745-0383E8DCBC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06BF0000 +// Image base: 0x06B90000 // =============== CLASS MEMBERS DECLARATION =================== @@ -123,13 +123,12 @@ .method public static void main@() cil managed { .entrypoint - // Code size 64 (0x40) + // Code size 56 (0x38) .maxstack 4 .locals init ([0] object o, [1] object V_1, [2] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_2, - [3] bool V_3, - [4] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_4) + [3] bool V_3) .line 19,19 : 1,28 '' IL_0000: newobj instance void [mscorlib]System.Object::.ctor() IL_0005: dup @@ -151,30 +150,24 @@ IL_0022: ldloc.2 IL_0023: ldnull IL_0024: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0029: stloc.s V_4 - IL_002b: leave.s IL_003c + IL_0029: pop + IL_002a: leave.s IL_0037 } // end .try finally { - IL_002d: ldloc.3 - IL_002e: brfalse.s IL_0039 + IL_002c: ldloc.3 + IL_002d: brfalse.s IL_0036 .line 100001,100001 : 0,0 '' - IL_0030: ldloc.1 - IL_0031: call void [netstandard]System.Threading.Monitor::Exit(object) - IL_0036: ldnull - IL_0037: pop - IL_0038: endfinally + IL_002f: ldloc.1 + IL_0030: call void [netstandard]System.Threading.Monitor::Exit(object) + IL_0035: endfinally .line 100001,100001 : 0,0 '' - IL_0039: ldnull - IL_003a: pop - IL_003b: endfinally + IL_0036: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_003c: ldloc.s V_4 - IL_003e: pop - IL_003f: ret + IL_0037: ret } // end of method $Lock01::main@ } // end of class ''.$Lock01 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/NoBoxingOnDispose01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/NoBoxingOnDispose01.il.bsl index 1c571a25e0b..570d4feb14e 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/NoBoxingOnDispose01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/NoBoxingOnDispose01.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000220 Length: 0x0000007F } .module NoBoxingOnDispose01.exe -// MVID: {60B68B7F-4EA9-C934-A745-03837F8BB660} +// MVID: {60BCDCE8-4EA9-C934-A745-0383E8DCBC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06C40000 +// Image base: 0x07070000 // =============== CLASS MEMBERS DECLARATION =================== @@ -53,12 +53,11 @@ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) .method public static void f1(class [mscorlib]System.Collections.Generic.List`1 x) cil managed { - // Code size 52 (0x34) + // Code size 46 (0x2e) .maxstack 3 .locals init ([0] class [mscorlib]System.Collections.Generic.List`1 V_0, [1] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator V_1, - [2] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_2, - [3] !!T a) + [2] !!T a) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' .line 6,6 : 3,16 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\Misc\\NoBoxingOnDispose01.fs' IL_0000: ldarg.0 @@ -76,29 +75,23 @@ .line 6,6 : 3,16 '' IL_0012: ldloca.s V_1 IL_0014: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator::get_Current() - IL_0019: stloc.3 + IL_0019: stloc.2 .line 100001,100001 : 0,0 '' IL_001a: nop IL_001b: br.s IL_0009 - IL_001d: ldnull - IL_001e: stloc.2 - IL_001f: leave.s IL_0031 + IL_001d: leave.s IL_002d } // end .try finally { - IL_0021: ldloca.s V_1 - IL_0023: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator - IL_0029: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_002e: ldnull - IL_002f: pop - IL_0030: endfinally + IL_001f: ldloca.s V_1 + IL_0021: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator + IL_0027: callvirt instance void [mscorlib]System.IDisposable::Dispose() + IL_002c: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_0031: ldloc.2 - IL_0032: pop - IL_0033: ret + IL_002d: ret } // end of method NoBoxingOnDispose01::f1 } // end of class NoBoxingOnDispose01 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/TryWith_NoFilterBlocks01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/TryWith_NoFilterBlocks01.il.bsl index d053449a8d5..db782e0d6c0 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/TryWith_NoFilterBlocks01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/TryWith_NoFilterBlocks01.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000160 Length: 0x0000005F } .module TryWith_NoFilterBlocks01.exe -// MVID: {60B68B7F-3DEF-9A40-A745-03837F8BB660} +// MVID: {60BCDCE8-3DEF-9A40-A745-0383E8DCBC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00F10000 +// Image base: 0x05100000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,51 +63,42 @@ .method public static void main@() cil managed { .entrypoint - // Code size 36 (0x24) + // Code size 28 (0x1c) .maxstack 4 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_0, - [1] class [mscorlib]System.Exception V_1, - [2] class [mscorlib]System.Exception e, - [3] class [mscorlib]System.Exception V_3) + .locals init ([0] class [mscorlib]System.Exception V_0, + [1] class [mscorlib]System.Exception e, + [2] class [mscorlib]System.Exception V_2) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' .line 4,4 : 3,5 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\Misc\\TryWith_NoFilterBlocks01.fs' .try { - IL_0000: ldnull - IL_0001: stloc.0 - IL_0002: leave.s IL_0021 + IL_0000: leave.s IL_001b .line 5,5 : 2,6 '' } // end .try catch [mscorlib]System.Object { - IL_0004: castclass [mscorlib]System.Exception + IL_0002: castclass [mscorlib]System.Exception + IL_0007: stloc.0 + IL_0008: ldloc.0 IL_0009: stloc.1 IL_000a: ldloc.1 - IL_000b: stloc.2 - IL_000c: ldloc.2 - IL_000d: callvirt instance int32 [mscorlib]System.Object::GetHashCode() - IL_0012: ldc.i4.0 - IL_0013: ceq - IL_0015: brfalse.s IL_001d - - IL_0017: ldloc.1 - IL_0018: stloc.3 + IL_000b: callvirt instance int32 [mscorlib]System.Object::GetHashCode() + IL_0010: ldc.i4.0 + IL_0011: ceq + IL_0013: brfalse.s IL_0019 + + IL_0015: ldloc.0 + IL_0016: stloc.2 .line 6,6 : 35,37 '' - IL_0019: ldnull - IL_001a: stloc.0 - IL_001b: leave.s IL_0021 + IL_0017: leave.s IL_001b .line 7,7 : 10,12 '' - IL_001d: ldnull - IL_001e: stloc.0 - IL_001f: leave.s IL_0021 + IL_0019: leave.s IL_001b .line 100001,100001 : 0,0 '' } // end handler - IL_0021: ldloc.0 - IL_0022: pop - IL_0023: ret + IL_001b: ret } // end of method $TryWith_NoFilterBlocks01::main@ } // end of class ''.$TryWith_NoFilterBlocks01 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.bsl index 725432edbd2..b951385cf75 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Aggregates01.il.bsl @@ -50,13 +50,13 @@ // Offset: 0x000005F0 Length: 0x00000211 } .module Linq101Aggregates01.exe -// MVID: {60B78A59-D281-4783-A745-0383598AB760} +// MVID: {60BD472F-D281-4783-A745-03832F47BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06380000 +// Image base: 0x05800000 // =============== CLASS MEMBERS DECLARATION =================== @@ -194,11 +194,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/uniqueFactors@12::pc @@ -210,7 +209,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -260,41 +259,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101Aggregates01/uniqueFactors@12::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 12,12 : 9,33 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method uniqueFactors@12::Close .method public strict virtual instance bool @@ -498,11 +490,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/numSum@21::pc @@ -514,7 +505,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -564,41 +555,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101Aggregates01/numSum@21::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 21,21 : 9,28 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method numSum@21::Close .method public strict virtual instance bool @@ -840,11 +824,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/totalChars@30::pc @@ -856,7 +839,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -906,41 +889,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101Aggregates01/totalChars@30::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 30,30 : 9,26 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method totalChars@30::Close .method public strict virtual instance bool @@ -1309,11 +1285,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/sum@42::pc @@ -1325,7 +1300,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -1375,41 +1350,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [Utils]Utils/Product Linq101Aggregates01/sum@42::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 42,42 : 13,26 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method sum@42::Close .method public strict virtual instance bool @@ -1553,7 +1521,7 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,int32>,object> Invoke(class [System.Core]System.Linq.IGrouping`2 _arg2) cil managed { - // Code size 141 (0x8d) + // Code size 137 (0x89) .maxstack 8 .locals init ([0] class [System.Core]System.Linq.IGrouping`2 g, [1] int32 sum, @@ -1613,7 +1581,7 @@ IL_0055: ldloc.s V_9 IL_0057: stloc.s V_8 - IL_0059: leave.s IL_0075 + IL_0059: leave.s IL_0071 } // end .try finally @@ -1622,32 +1590,28 @@ IL_005d: isinst [mscorlib]System.IDisposable IL_0062: stloc.s V_10 IL_0064: ldloc.s V_10 - IL_0066: brfalse.s IL_0072 + IL_0066: brfalse.s IL_0070 .line 100001,100001 : 0,0 '' IL_0068: ldloc.s V_10 IL_006a: callvirt instance void [netstandard]System.IDisposable::Dispose() - IL_006f: ldnull - IL_0070: pop - IL_0071: endfinally + IL_006f: endfinally .line 100001,100001 : 0,0 '' - IL_0072: ldnull - IL_0073: pop - IL_0074: endfinally + IL_0070: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_0075: ldloc.s V_8 - IL_0077: stloc.1 + IL_0071: ldloc.s V_8 + IL_0073: stloc.1 .line 45,45 : 9,28 '' - IL_0078: ldarg.0 - IL_0079: ldfld class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder Linq101Aggregates01/'categories@40-3'::builder@ - IL_007e: ldloc.0 - IL_007f: ldloc.1 - IL_0080: newobj instance void class [mscorlib]System.Tuple`2,int32>::.ctor(!0, + IL_0074: ldarg.0 + IL_0075: ldfld class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder Linq101Aggregates01/'categories@40-3'::builder@ + IL_007a: ldloc.0 + IL_007b: ldloc.1 + IL_007c: newobj instance void class [mscorlib]System.Tuple`2,int32>::.ctor(!0, !1) - IL_0085: tail. - IL_0087: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Yield,int32>,object>(!!0) - IL_008c: ret + IL_0081: tail. + IL_0083: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Yield,int32>,object>(!!0) + IL_0088: ret } // end of method 'categories@40-3'::Invoke } // end of class 'categories@40-3' @@ -1831,11 +1795,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/minNum@49::pc @@ -1847,7 +1810,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -1897,41 +1860,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101Aggregates01/minNum@49::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 49,49 : 22,41 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method minNum@49::Close .method public strict virtual instance bool @@ -2173,11 +2129,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/shortestWord@52::pc @@ -2189,7 +2144,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -2239,41 +2194,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101Aggregates01/shortestWord@52::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 52,52 : 28,45 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method shortestWord@52::Close .method public strict virtual instance bool @@ -2642,11 +2590,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/min@59::pc @@ -2658,7 +2605,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -2708,41 +2655,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [Utils]Utils/Product Linq101Aggregates01/min@59::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 59,59 : 27,40 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method min@59::Close .method public strict virtual instance bool @@ -3244,11 +3184,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/cheapestProducts@69::pc @@ -3260,7 +3199,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -3310,41 +3249,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [Utils]Utils/Product Linq101Aggregates01/cheapestProducts@69::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 69,69 : 40,53 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method cheapestProducts@69::Close .method public strict virtual instance bool @@ -3720,11 +3652,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/maxNum@74::pc @@ -3736,7 +3667,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -3786,41 +3717,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101Aggregates01/maxNum@74::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 74,74 : 22,41 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method maxNum@74::Close .method public strict virtual instance bool @@ -4062,11 +3986,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/longestLength@77::pc @@ -4078,7 +4001,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -4128,41 +4051,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101Aggregates01/longestLength@77::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 77,77 : 29,46 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method longestLength@77::Close .method public strict virtual instance bool @@ -4531,11 +4447,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/mostExpensivePrice@84::pc @@ -4547,7 +4462,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -4597,41 +4512,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [Utils]Utils/Product Linq101Aggregates01/mostExpensivePrice@84::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 84,84 : 42,55 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method mostExpensivePrice@84::Close .method public strict virtual instance bool @@ -5115,11 +5023,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/maxPrice@93::pc @@ -5131,7 +5038,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -5181,41 +5088,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [Utils]Utils/Product Linq101Aggregates01/maxPrice@93::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 93,93 : 32,45 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method maxPrice@93::Close .method public strict virtual instance bool @@ -5468,11 +5368,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/mostExpensiveProducts@94::pc @@ -5484,7 +5383,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -5534,41 +5433,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [Utils]Utils/Product Linq101Aggregates01/mostExpensiveProducts@94::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 94,94 : 45,58 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method mostExpensiveProducts@94::Close .method public strict virtual instance bool @@ -5949,11 +5841,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 144 (0x90) + // Code size 135 (0x87) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/averageNum@100::pc @@ -5961,95 +5852,88 @@ IL_0007: sub IL_0008: switch ( IL_0013) - IL_0011: br.s IL_0019 + IL_0011: br.s IL_0016 .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br IL_0087 + IL_0014: br.s IL_007e .line 100001,100001 : 0,0 '' - IL_0019: nop + IL_0016: nop .try { - IL_001a: ldarg.0 - IL_001b: ldfld int32 Linq101Aggregates01/averageNum@100::pc - IL_0020: switch ( + IL_0017: ldarg.0 + IL_0018: ldfld int32 Linq101Aggregates01/averageNum@100::pc + IL_001d: switch ( + IL_0034, IL_0037, IL_003a, - IL_003d, - IL_0040) - IL_0035: br.s IL_0043 + IL_003d) + IL_0032: br.s IL_0040 + + .line 100001,100001 : 0,0 '' + IL_0034: nop + IL_0035: br.s IL_0056 .line 100001,100001 : 0,0 '' IL_0037: nop - IL_0038: br.s IL_0059 + IL_0038: br.s IL_0042 .line 100001,100001 : 0,0 '' IL_003a: nop - IL_003b: br.s IL_0045 + IL_003b: br.s IL_0041 .line 100001,100001 : 0,0 '' IL_003d: nop - IL_003e: br.s IL_0044 + IL_003e: br.s IL_0056 .line 100001,100001 : 0,0 '' IL_0040: nop - IL_0041: br.s IL_0059 - - .line 100001,100001 : 0,0 '' - IL_0043: nop - .line 100001,100001 : 0,0 '' - IL_0044: nop - IL_0045: ldarg.0 - IL_0046: ldc.i4.3 - IL_0047: stfld int32 Linq101Aggregates01/averageNum@100::pc - IL_004c: ldarg.0 - IL_004d: ldfld class [mscorlib]System.Collections.Generic.IEnumerator`1 Linq101Aggregates01/averageNum@100::'enum' - IL_0052: call void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::Dispose>(!!0) - IL_0057: nop - .line 100001,100001 : 0,0 '' - IL_0058: nop - IL_0059: ldarg.0 - IL_005a: ldc.i4.3 - IL_005b: stfld int32 Linq101Aggregates01/averageNum@100::pc - IL_0060: ldarg.0 - IL_0061: ldc.r8 0.0 - IL_006a: stfld float64 Linq101Aggregates01/averageNum@100::current - IL_006f: ldnull - IL_0070: stloc.1 - IL_0071: leave.s IL_007f + .line 100001,100001 : 0,0 '' + IL_0041: nop + IL_0042: ldarg.0 + IL_0043: ldc.i4.3 + IL_0044: stfld int32 Linq101Aggregates01/averageNum@100::pc + IL_0049: ldarg.0 + IL_004a: ldfld class [mscorlib]System.Collections.Generic.IEnumerator`1 Linq101Aggregates01/averageNum@100::'enum' + IL_004f: call void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::Dispose>(!!0) + IL_0054: nop + .line 100001,100001 : 0,0 '' + IL_0055: nop + IL_0056: ldarg.0 + IL_0057: ldc.i4.3 + IL_0058: stfld int32 Linq101Aggregates01/averageNum@100::pc + IL_005d: ldarg.0 + IL_005e: ldc.r8 0.0 + IL_0067: stfld float64 Linq101Aggregates01/averageNum@100::current + IL_006c: leave.s IL_0078 } // end .try catch [mscorlib]System.Object { - IL_0073: castclass [mscorlib]System.Exception - IL_0078: stloc.2 + IL_006e: castclass [mscorlib]System.Exception + IL_0073: stloc.1 .line 100,100 : 26,46 '' - IL_0079: ldloc.2 - IL_007a: stloc.0 - IL_007b: ldnull - IL_007c: stloc.1 - IL_007d: leave.s IL_007f + IL_0074: ldloc.1 + IL_0075: stloc.0 + IL_0076: leave.s IL_0078 .line 100001,100001 : 0,0 '' } // end handler - IL_007f: ldloc.1 - IL_0080: pop - .line 100001,100001 : 0,0 '' - IL_0081: nop - IL_0082: br IL_0000 + IL_0078: nop + IL_0079: br IL_0000 - IL_0087: ldloc.0 - IL_0088: ldnull - IL_0089: cgt.un - IL_008b: brfalse.s IL_008f + IL_007e: ldloc.0 + IL_007f: ldnull + IL_0080: cgt.un + IL_0082: brfalse.s IL_0086 .line 100001,100001 : 0,0 '' - IL_008d: ldloc.0 - IL_008e: throw + IL_0084: ldloc.0 + IL_0085: throw .line 100001,100001 : 0,0 '' - IL_008f: ret + IL_0086: ret } // end of method averageNum@100::Close .method public strict virtual instance bool @@ -6515,11 +6399,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Aggregates01/averagePrice@115::pc @@ -6531,7 +6414,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -6581,41 +6464,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [Utils]Utils/Product Linq101Aggregates01/averagePrice@115::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 115,115 : 36,49 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method averagePrice@115::Close .method public strict virtual instance bool @@ -6759,7 +6635,7 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,valuetype [mscorlib]System.Decimal>,object> Invoke(class [System.Core]System.Linq.IGrouping`2 _arg2) cil managed { - // Code size 222 (0xde) + // Code size 216 (0xd8) .maxstack 9 .locals init ([0] class [System.Core]System.Linq.IGrouping`2 g, [1] valuetype [mscorlib]System.Decimal averagePrice, @@ -6799,111 +6675,105 @@ IL_0028: stloc.s V_6 IL_002a: ldloc.s V_6 IL_002c: box class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_0031: brfalse.s IL_0035 - - IL_0033: br.s IL_0040 + IL_0031: brtrue.s IL_003e .line 100001,100001 : 0,0 '' - IL_0035: ldstr "source" - IL_003a: newobj instance void [netstandard]System.ArgumentNullException::.ctor(string) - IL_003f: throw + IL_0033: ldstr "source" + IL_0038: newobj instance void [netstandard]System.ArgumentNullException::.ctor(string) + IL_003d: throw .line 100001,100001 : 0,0 '' - IL_0040: nop - IL_0041: ldloc.s V_6 - IL_0043: callvirt instance class [netstandard]System.Collections.Generic.IEnumerator`1 class [netstandard]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_0048: stloc.s V_7 + IL_003e: nop + IL_003f: ldloc.s V_6 + IL_0041: callvirt instance class [netstandard]System.Collections.Generic.IEnumerator`1 class [netstandard]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_0046: stloc.s V_7 .try { + IL_0048: ldc.i4.0 + IL_0049: ldc.i4.0 IL_004a: ldc.i4.0 IL_004b: ldc.i4.0 IL_004c: ldc.i4.0 - IL_004d: ldc.i4.0 - IL_004e: ldc.i4.0 - IL_004f: newobj instance void [netstandard]System.Decimal::.ctor(int32, + IL_004d: newobj instance void [netstandard]System.Decimal::.ctor(int32, int32, int32, bool, uint8) - IL_0054: stloc.s V_9 - IL_0056: ldc.i4.0 - IL_0057: stloc.s V_10 - IL_0059: ldloc.s V_7 - IL_005b: callvirt instance bool [netstandard]System.Collections.IEnumerator::MoveNext() - IL_0060: brfalse.s IL_0082 - - IL_0062: ldloc.s V_9 - IL_0064: ldloc.s V_5 - IL_0066: ldloc.s V_7 - IL_0068: callvirt instance !0 class [netstandard]System.Collections.Generic.IEnumerator`1::get_Current() - IL_006d: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0072: call valuetype [netstandard]System.Decimal [netstandard]System.Decimal::op_Addition(valuetype [netstandard]System.Decimal, + IL_0052: stloc.s V_9 + IL_0054: ldc.i4.0 + IL_0055: stloc.s V_10 + IL_0057: ldloc.s V_7 + IL_0059: callvirt instance bool [netstandard]System.Collections.IEnumerator::MoveNext() + IL_005e: brfalse.s IL_0080 + + IL_0060: ldloc.s V_9 + IL_0062: ldloc.s V_5 + IL_0064: ldloc.s V_7 + IL_0066: callvirt instance !0 class [netstandard]System.Collections.Generic.IEnumerator`1::get_Current() + IL_006b: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0070: call valuetype [netstandard]System.Decimal [netstandard]System.Decimal::op_Addition(valuetype [netstandard]System.Decimal, valuetype [netstandard]System.Decimal) - IL_0077: stloc.s V_9 + IL_0075: stloc.s V_9 .line 115,115 : 50,71 '' - IL_0079: ldloc.s V_10 - IL_007b: ldc.i4.1 - IL_007c: add - IL_007d: stloc.s V_10 + IL_0077: ldloc.s V_10 + IL_0079: ldc.i4.1 + IL_007a: add + IL_007b: stloc.s V_10 .line 100001,100001 : 0,0 '' - IL_007f: nop - IL_0080: br.s IL_0059 + IL_007d: nop + IL_007e: br.s IL_0057 - IL_0082: ldloc.s V_10 - IL_0084: brtrue.s IL_0091 + IL_0080: ldloc.s V_10 + IL_0082: brtrue.s IL_008f .line 100001,100001 : 0,0 '' - IL_0086: ldstr "source" - IL_008b: newobj instance void [netstandard]System.InvalidOperationException::.ctor(string) - IL_0090: throw + IL_0084: ldstr "source" + IL_0089: newobj instance void [netstandard]System.InvalidOperationException::.ctor(string) + IL_008e: throw .line 100001,100001 : 0,0 '' - IL_0091: nop - IL_0092: ldloc.s V_9 - IL_0094: stloc.s V_11 - IL_0096: ldloc.s V_10 - IL_0098: stloc.s V_12 - IL_009a: ldloc.s V_11 - IL_009c: ldloc.s V_12 - IL_009e: call valuetype [netstandard]System.Decimal [netstandard]System.Convert::ToDecimal(int32) - IL_00a3: call valuetype [netstandard]System.Decimal [netstandard]System.Decimal::Divide(valuetype [netstandard]System.Decimal, + IL_008f: nop + IL_0090: ldloc.s V_9 + IL_0092: stloc.s V_11 + IL_0094: ldloc.s V_10 + IL_0096: stloc.s V_12 + IL_0098: ldloc.s V_11 + IL_009a: ldloc.s V_12 + IL_009c: call valuetype [netstandard]System.Decimal [netstandard]System.Convert::ToDecimal(int32) + IL_00a1: call valuetype [netstandard]System.Decimal [netstandard]System.Decimal::Divide(valuetype [netstandard]System.Decimal, valuetype [netstandard]System.Decimal) - IL_00a8: stloc.s V_8 - IL_00aa: leave.s IL_00c6 + IL_00a6: stloc.s V_8 + IL_00a8: leave.s IL_00c0 } // end .try finally { - IL_00ac: ldloc.s V_7 - IL_00ae: isinst [mscorlib]System.IDisposable - IL_00b3: stloc.s V_13 - IL_00b5: ldloc.s V_13 - IL_00b7: brfalse.s IL_00c3 + IL_00aa: ldloc.s V_7 + IL_00ac: isinst [mscorlib]System.IDisposable + IL_00b1: stloc.s V_13 + IL_00b3: ldloc.s V_13 + IL_00b5: brfalse.s IL_00bf .line 100001,100001 : 0,0 '' - IL_00b9: ldloc.s V_13 - IL_00bb: callvirt instance void [netstandard]System.IDisposable::Dispose() - IL_00c0: ldnull - IL_00c1: pop - IL_00c2: endfinally + IL_00b7: ldloc.s V_13 + IL_00b9: callvirt instance void [netstandard]System.IDisposable::Dispose() + IL_00be: endfinally .line 100001,100001 : 0,0 '' - IL_00c3: ldnull - IL_00c4: pop - IL_00c5: endfinally + IL_00bf: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_00c6: ldloc.s V_8 - IL_00c8: stloc.1 + IL_00c0: ldloc.s V_8 + IL_00c2: stloc.1 .line 116,116 : 9,37 '' - IL_00c9: ldarg.0 - IL_00ca: ldfld class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder Linq101Aggregates01/'categories6@114-3'::builder@ - IL_00cf: ldloc.0 - IL_00d0: ldloc.1 - IL_00d1: newobj instance void class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>::.ctor(!0, + IL_00c3: ldarg.0 + IL_00c4: ldfld class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder Linq101Aggregates01/'categories6@114-3'::builder@ + IL_00c9: ldloc.0 + IL_00ca: ldloc.1 + IL_00cb: newobj instance void class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>::.ctor(!0, !1) - IL_00d6: tail. - IL_00d8: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Yield,valuetype [mscorlib]System.Decimal>,object>(!!0) - IL_00dd: ret + IL_00d0: tail. + IL_00d2: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Yield,valuetype [mscorlib]System.Decimal>,object>(!!0) + IL_00d7: ret } // end of method 'categories6@114-3'::Invoke } // end of class 'categories6@114-3' @@ -7302,7 +7172,7 @@ .method public static void main@() cil managed { .entrypoint - // Code size 1741 (0x6cd) + // Code size 1721 (0x6b9) .maxstack 13 .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 factorsOf300, [1] int32 uniqueFactors, @@ -7487,7 +7357,7 @@ IL_00f4: ldloc.s V_28 IL_00f6: stloc.s V_27 - IL_00f8: leave.s IL_0114 + IL_00f8: leave.s IL_0110 } // end .try finally @@ -7496,601 +7366,581 @@ IL_00fc: isinst [mscorlib]System.IDisposable IL_0101: stloc.s V_29 IL_0103: ldloc.s V_29 - IL_0105: brfalse.s IL_0111 + IL_0105: brfalse.s IL_010f .line 100001,100001 : 0,0 '' IL_0107: ldloc.s V_29 IL_0109: callvirt instance void [netstandard]System.IDisposable::Dispose() - IL_010e: ldnull - IL_010f: pop - IL_0110: endfinally + IL_010e: endfinally .line 100001,100001 : 0,0 '' - IL_0111: ldnull - IL_0112: pop - IL_0113: endfinally + IL_010f: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_0114: ldloc.s V_27 - IL_0116: dup - IL_0117: stsfld int32 ''.$Linq101Aggregates01::numSum@19 - IL_011c: stloc.3 + IL_0110: ldloc.s V_27 + IL_0112: dup + IL_0113: stsfld int32 ''.$Linq101Aggregates01::numSum@19 + IL_0118: stloc.3 .line 26,26 : 1,45 '' - IL_011d: ldstr "cherry" - IL_0122: ldstr "apple" - IL_0127: ldstr "blueberry" - IL_012c: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() - IL_0131: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0119: ldstr "cherry" + IL_011e: ldstr "apple" + IL_0123: ldstr "blueberry" + IL_0128: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_012d: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0136: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0132: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_013b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0137: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_0140: dup - IL_0141: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::words@26 - IL_0146: stloc.s words - IL_0148: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_014d: stloc.s V_30 - IL_014f: ldloc.s V_30 - IL_0151: stloc.s V_31 - IL_0153: ldnull - IL_0154: ldc.i4.0 - IL_0155: ldnull - IL_0156: newobj instance void Linq101Aggregates01/totalChars@30::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, + IL_013c: dup + IL_013d: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::words@26 + IL_0142: stloc.s words + IL_0144: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0149: stloc.s V_30 + IL_014b: ldloc.s V_30 + IL_014d: stloc.s V_31 + IL_014f: ldnull + IL_0150: ldc.i4.0 + IL_0151: ldnull + IL_0152: newobj instance void Linq101Aggregates01/totalChars@30::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, string) - IL_015b: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0160: stloc.s V_32 - IL_0162: ldsfld class Linq101Aggregates01/'totalChars@31-1' Linq101Aggregates01/'totalChars@31-1'::@_instance - IL_0167: stloc.s V_33 - IL_0169: ldloc.s V_32 - IL_016b: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() - IL_0170: stloc.s V_34 - IL_0172: ldloc.s V_34 - IL_0174: callvirt instance class [netstandard]System.Collections.Generic.IEnumerator`1 class [netstandard]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_0179: stloc.s V_35 + IL_0157: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_015c: stloc.s V_32 + IL_015e: ldsfld class Linq101Aggregates01/'totalChars@31-1' Linq101Aggregates01/'totalChars@31-1'::@_instance + IL_0163: stloc.s V_33 + IL_0165: ldloc.s V_32 + IL_0167: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() + IL_016c: stloc.s V_34 + IL_016e: ldloc.s V_34 + IL_0170: callvirt instance class [netstandard]System.Collections.Generic.IEnumerator`1 class [netstandard]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_0175: stloc.s V_35 .try { - IL_017b: ldc.i4.0 - IL_017c: stloc.s V_37 - IL_017e: ldloc.s V_35 - IL_0180: callvirt instance bool [netstandard]System.Collections.IEnumerator::MoveNext() - IL_0185: brfalse.s IL_019d + IL_0177: ldc.i4.0 + IL_0178: stloc.s V_37 + IL_017a: ldloc.s V_35 + IL_017c: callvirt instance bool [netstandard]System.Collections.IEnumerator::MoveNext() + IL_0181: brfalse.s IL_0199 .line 31,31 : 9,25 '' - IL_0187: ldloc.s V_37 - IL_0189: ldloc.s V_33 - IL_018b: ldloc.s V_35 - IL_018d: callvirt instance !0 class [netstandard]System.Collections.Generic.IEnumerator`1::get_Current() - IL_0192: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0197: add.ovf - IL_0198: stloc.s V_37 + IL_0183: ldloc.s V_37 + IL_0185: ldloc.s V_33 + IL_0187: ldloc.s V_35 + IL_0189: callvirt instance !0 class [netstandard]System.Collections.Generic.IEnumerator`1::get_Current() + IL_018e: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0193: add.ovf + IL_0194: stloc.s V_37 .line 100001,100001 : 0,0 '' - IL_019a: nop - IL_019b: br.s IL_017e + IL_0196: nop + IL_0197: br.s IL_017a - IL_019d: ldloc.s V_37 - IL_019f: stloc.s V_36 - IL_01a1: leave.s IL_01bd + IL_0199: ldloc.s V_37 + IL_019b: stloc.s V_36 + IL_019d: leave.s IL_01b5 } // end .try finally { - IL_01a3: ldloc.s V_35 - IL_01a5: isinst [mscorlib]System.IDisposable - IL_01aa: stloc.s V_38 - IL_01ac: ldloc.s V_38 - IL_01ae: brfalse.s IL_01ba + IL_019f: ldloc.s V_35 + IL_01a1: isinst [mscorlib]System.IDisposable + IL_01a6: stloc.s V_38 + IL_01a8: ldloc.s V_38 + IL_01aa: brfalse.s IL_01b4 .line 100001,100001 : 0,0 '' - IL_01b0: ldloc.s V_38 - IL_01b2: callvirt instance void [netstandard]System.IDisposable::Dispose() - IL_01b7: ldnull - IL_01b8: pop - IL_01b9: endfinally + IL_01ac: ldloc.s V_38 + IL_01ae: callvirt instance void [netstandard]System.IDisposable::Dispose() + IL_01b3: endfinally .line 100001,100001 : 0,0 '' - IL_01ba: ldnull - IL_01bb: pop - IL_01bc: endfinally + IL_01b4: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_01bd: ldloc.s V_36 - IL_01bf: dup - IL_01c0: stsfld int32 ''.$Linq101Aggregates01::totalChars@28 - IL_01c5: stloc.s totalChars + IL_01b5: ldloc.s V_36 + IL_01b7: dup + IL_01b8: stsfld int32 ''.$Linq101Aggregates01::totalChars@28 + IL_01bd: stloc.s totalChars .line 35,35 : 1,32 '' - IL_01c7: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [Utils]Utils::getProductList() - IL_01cc: dup - IL_01cd: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::products@35 - IL_01d2: stloc.s products + IL_01bf: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [Utils]Utils::getProductList() + IL_01c4: dup + IL_01c5: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::products@35 + IL_01ca: stloc.s products .line 37,46 : 1,21 '' - IL_01d4: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_01d9: stloc.s V_39 + IL_01cc: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_01d1: stloc.s V_39 + IL_01d3: ldloc.s V_39 + IL_01d5: ldloc.s V_39 + IL_01d7: ldloc.s V_39 + IL_01d9: ldloc.s V_39 IL_01db: ldloc.s V_39 - IL_01dd: ldloc.s V_39 - IL_01df: ldloc.s V_39 - IL_01e1: ldloc.s V_39 - IL_01e3: ldloc.s V_39 - IL_01e5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_01ea: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_01ef: ldloc.s V_39 - IL_01f1: newobj instance void Linq101Aggregates01/categories@39::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_01f6: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_01dd: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_01e2: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_01e7: ldloc.s V_39 + IL_01e9: newobj instance void Linq101Aggregates01/categories@39::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_01ee: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_01fb: ldsfld class Linq101Aggregates01/'categories@40-1' Linq101Aggregates01/'categories@40-1'::@_instance - IL_0200: ldsfld class Linq101Aggregates01/'categories@40-2' Linq101Aggregates01/'categories@40-2'::@_instance - IL_0205: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_01f3: ldsfld class Linq101Aggregates01/'categories@40-1' Linq101Aggregates01/'categories@40-1'::@_instance + IL_01f8: ldsfld class Linq101Aggregates01/'categories@40-2' Linq101Aggregates01/'categories@40-2'::@_instance + IL_01fd: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_020a: ldloc.s V_39 - IL_020c: newobj instance void Linq101Aggregates01/'categories@40-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0211: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,int32>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0202: ldloc.s V_39 + IL_0204: newobj instance void Linq101Aggregates01/'categories@40-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0209: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,int32>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0216: ldsfld class Linq101Aggregates01/'categories@45-4' Linq101Aggregates01/'categories@45-4'::@_instance - IL_021b: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,int32>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_020e: ldsfld class Linq101Aggregates01/'categories@45-4' Linq101Aggregates01/'categories@45-4'::@_instance + IL_0213: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,int32>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0220: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_0225: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_022a: dup - IL_022b: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories@37 - IL_0230: stloc.s categories - IL_0232: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0237: ldnull - IL_0238: ldc.i4.0 - IL_0239: ldc.i4.0 - IL_023a: newobj instance void Linq101Aggregates01/minNum@49::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, + IL_0218: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_021d: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0222: dup + IL_0223: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories@37 + IL_0228: stloc.s categories + IL_022a: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_022f: ldnull + IL_0230: ldc.i4.0 + IL_0231: ldc.i4.0 + IL_0232: newobj instance void Linq101Aggregates01/minNum@49::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, int32) - IL_023f: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0244: ldsfld class Linq101Aggregates01/'minNum@49-1' Linq101Aggregates01/'minNum@49-1'::@_instance - IL_0249: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0237: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_023c: ldsfld class Linq101Aggregates01/'minNum@49-1' Linq101Aggregates01/'minNum@49-1'::@_instance + IL_0241: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_024e: dup - IL_024f: stsfld int32 ''.$Linq101Aggregates01::minNum@49 - IL_0254: stloc.s minNum - IL_0256: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_025b: ldnull - IL_025c: ldc.i4.0 - IL_025d: ldnull - IL_025e: newobj instance void Linq101Aggregates01/shortestWord@52::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, + IL_0246: dup + IL_0247: stsfld int32 ''.$Linq101Aggregates01::minNum@49 + IL_024c: stloc.s minNum + IL_024e: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0253: ldnull + IL_0254: ldc.i4.0 + IL_0255: ldnull + IL_0256: newobj instance void Linq101Aggregates01/shortestWord@52::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, string) - IL_0263: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0268: ldsfld class Linq101Aggregates01/'shortestWord@52-1' Linq101Aggregates01/'shortestWord@52-1'::@_instance - IL_026d: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_025b: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0260: ldsfld class Linq101Aggregates01/'shortestWord@52-1' Linq101Aggregates01/'shortestWord@52-1'::@_instance + IL_0265: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MinBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0272: dup - IL_0273: stsfld int32 ''.$Linq101Aggregates01::shortestWord@52 - IL_0278: stloc.s shortestWord + IL_026a: dup + IL_026b: stsfld int32 ''.$Linq101Aggregates01::shortestWord@52 + IL_0270: stloc.s shortestWord .line 55,61 : 1,21 '' - IL_027a: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_027f: stloc.s V_40 + IL_0272: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0277: stloc.s V_40 + IL_0279: ldloc.s V_40 + IL_027b: ldloc.s V_40 + IL_027d: ldloc.s V_40 + IL_027f: ldloc.s V_40 IL_0281: ldloc.s V_40 - IL_0283: ldloc.s V_40 - IL_0285: ldloc.s V_40 - IL_0287: ldloc.s V_40 - IL_0289: ldloc.s V_40 - IL_028b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_0290: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0295: ldloc.s V_40 - IL_0297: newobj instance void Linq101Aggregates01/categories2@57::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_029c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0283: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_0288: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_028d: ldloc.s V_40 + IL_028f: newobj instance void Linq101Aggregates01/categories2@57::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0294: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_02a1: ldsfld class Linq101Aggregates01/'categories2@58-1' Linq101Aggregates01/'categories2@58-1'::@_instance - IL_02a6: ldsfld class Linq101Aggregates01/'categories2@58-2' Linq101Aggregates01/'categories2@58-2'::@_instance - IL_02ab: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0299: ldsfld class Linq101Aggregates01/'categories2@58-1' Linq101Aggregates01/'categories2@58-1'::@_instance + IL_029e: ldsfld class Linq101Aggregates01/'categories2@58-2' Linq101Aggregates01/'categories2@58-2'::@_instance + IL_02a3: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_02b0: ldloc.s V_40 - IL_02b2: newobj instance void Linq101Aggregates01/'categories2@58-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_02b7: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_02a8: ldloc.s V_40 + IL_02aa: newobj instance void Linq101Aggregates01/'categories2@58-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_02af: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_02bc: ldsfld class Linq101Aggregates01/'categories2@60-4' Linq101Aggregates01/'categories2@60-4'::@_instance - IL_02c1: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_02b4: ldsfld class Linq101Aggregates01/'categories2@60-4' Linq101Aggregates01/'categories2@60-4'::@_instance + IL_02b9: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_02c6: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_02cb: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_02d0: dup - IL_02d1: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories2@55 - IL_02d6: stloc.s categories2 + IL_02be: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_02c3: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_02c8: dup + IL_02c9: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories2@55 + IL_02ce: stloc.s categories2 .line 64,71 : 1,21 '' - IL_02d8: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_02dd: stloc.s V_41 + IL_02d0: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_02d5: stloc.s V_41 + IL_02d7: ldloc.s V_41 + IL_02d9: ldloc.s V_41 + IL_02db: ldloc.s V_41 + IL_02dd: ldloc.s V_41 IL_02df: ldloc.s V_41 - IL_02e1: ldloc.s V_41 - IL_02e3: ldloc.s V_41 - IL_02e5: ldloc.s V_41 - IL_02e7: ldloc.s V_41 - IL_02e9: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_02ee: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_02f3: ldloc.s V_41 - IL_02f5: newobj instance void Linq101Aggregates01/categories3@66::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_02fa: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_02e1: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_02e6: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_02eb: ldloc.s V_41 + IL_02ed: newobj instance void Linq101Aggregates01/categories3@66::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_02f2: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_02ff: ldsfld class Linq101Aggregates01/'categories3@67-1' Linq101Aggregates01/'categories3@67-1'::@_instance - IL_0304: ldsfld class Linq101Aggregates01/'categories3@67-2' Linq101Aggregates01/'categories3@67-2'::@_instance - IL_0309: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_02f7: ldsfld class Linq101Aggregates01/'categories3@67-1' Linq101Aggregates01/'categories3@67-1'::@_instance + IL_02fc: ldsfld class Linq101Aggregates01/'categories3@67-2' Linq101Aggregates01/'categories3@67-2'::@_instance + IL_0301: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_030e: ldloc.s V_41 - IL_0310: newobj instance void Linq101Aggregates01/'categories3@67-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0315: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0306: ldloc.s V_41 + IL_0308: newobj instance void Linq101Aggregates01/'categories3@67-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_030d: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_031a: ldsfld class Linq101Aggregates01/'categories3@70-4' Linq101Aggregates01/'categories3@70-4'::@_instance - IL_031f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0312: ldsfld class Linq101Aggregates01/'categories3@70-4' Linq101Aggregates01/'categories3@70-4'::@_instance + IL_0317: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0324: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_0329: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_032e: dup - IL_032f: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories3@64 - IL_0334: stloc.s categories3 - IL_0336: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_033b: ldnull - IL_033c: ldc.i4.0 - IL_033d: ldc.i4.0 - IL_033e: newobj instance void Linq101Aggregates01/maxNum@74::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, + IL_031c: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_0321: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0326: dup + IL_0327: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories3@64 + IL_032c: stloc.s categories3 + IL_032e: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0333: ldnull + IL_0334: ldc.i4.0 + IL_0335: ldc.i4.0 + IL_0336: newobj instance void Linq101Aggregates01/maxNum@74::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, int32) - IL_0343: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0348: ldsfld class Linq101Aggregates01/'maxNum@74-1' Linq101Aggregates01/'maxNum@74-1'::@_instance - IL_034d: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_033b: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0340: ldsfld class Linq101Aggregates01/'maxNum@74-1' Linq101Aggregates01/'maxNum@74-1'::@_instance + IL_0345: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0352: dup - IL_0353: stsfld int32 ''.$Linq101Aggregates01::maxNum@74 - IL_0358: stloc.s maxNum - IL_035a: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_035f: ldnull - IL_0360: ldc.i4.0 - IL_0361: ldnull - IL_0362: newobj instance void Linq101Aggregates01/longestLength@77::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, + IL_034a: dup + IL_034b: stsfld int32 ''.$Linq101Aggregates01::maxNum@74 + IL_0350: stloc.s maxNum + IL_0352: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0357: ldnull + IL_0358: ldc.i4.0 + IL_0359: ldnull + IL_035a: newobj instance void Linq101Aggregates01/longestLength@77::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, string) - IL_0367: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_036c: ldsfld class Linq101Aggregates01/'longestLength@77-1' Linq101Aggregates01/'longestLength@77-1'::@_instance - IL_0371: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_035f: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0364: ldsfld class Linq101Aggregates01/'longestLength@77-1' Linq101Aggregates01/'longestLength@77-1'::@_instance + IL_0369: callvirt instance !!2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::MaxBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0376: dup - IL_0377: stsfld int32 ''.$Linq101Aggregates01::longestLength@77 - IL_037c: stloc.s longestLength + IL_036e: dup + IL_036f: stsfld int32 ''.$Linq101Aggregates01::longestLength@77 + IL_0374: stloc.s longestLength .line 80,86 : 1,21 '' - IL_037e: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0383: stloc.s V_42 + IL_0376: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_037b: stloc.s V_42 + IL_037d: ldloc.s V_42 + IL_037f: ldloc.s V_42 + IL_0381: ldloc.s V_42 + IL_0383: ldloc.s V_42 IL_0385: ldloc.s V_42 - IL_0387: ldloc.s V_42 - IL_0389: ldloc.s V_42 - IL_038b: ldloc.s V_42 - IL_038d: ldloc.s V_42 - IL_038f: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_0394: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0399: ldloc.s V_42 - IL_039b: newobj instance void Linq101Aggregates01/categories4@82::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_03a0: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0387: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_038c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_0391: ldloc.s V_42 + IL_0393: newobj instance void Linq101Aggregates01/categories4@82::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0398: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_03a5: ldsfld class Linq101Aggregates01/'categories4@83-1' Linq101Aggregates01/'categories4@83-1'::@_instance - IL_03aa: ldsfld class Linq101Aggregates01/'categories4@83-2' Linq101Aggregates01/'categories4@83-2'::@_instance - IL_03af: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_039d: ldsfld class Linq101Aggregates01/'categories4@83-1' Linq101Aggregates01/'categories4@83-1'::@_instance + IL_03a2: ldsfld class Linq101Aggregates01/'categories4@83-2' Linq101Aggregates01/'categories4@83-2'::@_instance + IL_03a7: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_03b4: ldloc.s V_42 - IL_03b6: newobj instance void Linq101Aggregates01/'categories4@83-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_03bb: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03ac: ldloc.s V_42 + IL_03ae: newobj instance void Linq101Aggregates01/'categories4@83-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_03b3: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_03c0: ldsfld class Linq101Aggregates01/'categories4@85-4' Linq101Aggregates01/'categories4@85-4'::@_instance - IL_03c5: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03b8: ldsfld class Linq101Aggregates01/'categories4@85-4' Linq101Aggregates01/'categories4@85-4'::@_instance + IL_03bd: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_03ca: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_03cf: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_03d4: dup - IL_03d5: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories4@80 - IL_03da: stloc.s categories4 + IL_03c2: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_03c7: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_03cc: dup + IL_03cd: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories4@80 + IL_03d2: stloc.s categories4 .line 89,96 : 1,21 '' - IL_03dc: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_03e1: stloc.s V_43 + IL_03d4: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_03d9: stloc.s V_43 + IL_03db: ldloc.s V_43 + IL_03dd: ldloc.s V_43 + IL_03df: ldloc.s V_43 + IL_03e1: ldloc.s V_43 IL_03e3: ldloc.s V_43 - IL_03e5: ldloc.s V_43 - IL_03e7: ldloc.s V_43 - IL_03e9: ldloc.s V_43 - IL_03eb: ldloc.s V_43 - IL_03ed: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_03f2: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_03f7: ldloc.s V_43 - IL_03f9: newobj instance void Linq101Aggregates01/categories5@91::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_03fe: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03e5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_03ea: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_03ef: ldloc.s V_43 + IL_03f1: newobj instance void Linq101Aggregates01/categories5@91::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_03f6: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0403: ldsfld class Linq101Aggregates01/'categories5@92-1' Linq101Aggregates01/'categories5@92-1'::@_instance - IL_0408: ldsfld class Linq101Aggregates01/'categories5@92-2' Linq101Aggregates01/'categories5@92-2'::@_instance - IL_040d: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_03fb: ldsfld class Linq101Aggregates01/'categories5@92-1' Linq101Aggregates01/'categories5@92-1'::@_instance + IL_0400: ldsfld class Linq101Aggregates01/'categories5@92-2' Linq101Aggregates01/'categories5@92-2'::@_instance + IL_0405: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0412: ldloc.s V_43 - IL_0414: newobj instance void Linq101Aggregates01/'categories5@92-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0419: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_040a: ldloc.s V_43 + IL_040c: newobj instance void Linq101Aggregates01/'categories5@92-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0411: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`3,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_041e: ldsfld class Linq101Aggregates01/'categories5@95-4' Linq101Aggregates01/'categories5@95-4'::@_instance - IL_0423: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0416: ldsfld class Linq101Aggregates01/'categories5@95-4' Linq101Aggregates01/'categories5@95-4'::@_instance + IL_041b: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal,class [mscorlib]System.Collections.Generic.IEnumerable`1>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0428: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_042d: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0432: dup - IL_0433: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories5@89 - IL_0438: stloc.s categories5 + IL_0420: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2>,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_0425: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_042a: dup + IL_042b: stsfld class [mscorlib]System.Tuple`2>[] ''.$Linq101Aggregates01::categories5@89 + IL_0430: stloc.s categories5 .line 99,99 : 1,66 '' - IL_043a: ldc.r8 5. - IL_0443: ldc.r8 4. - IL_044c: ldc.r8 1. - IL_0455: ldc.r8 3. - IL_045e: ldc.r8 9. - IL_0467: ldc.r8 8. - IL_0470: ldc.r8 6. - IL_0479: ldc.r8 7. - IL_0482: ldc.r8 2. - IL_048b: ldc.r8 0.0 - IL_0494: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() - IL_0499: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0432: ldc.r8 5. + IL_043b: ldc.r8 4. + IL_0444: ldc.r8 1. + IL_044d: ldc.r8 3. + IL_0456: ldc.r8 9. + IL_045f: ldc.r8 8. + IL_0468: ldc.r8 6. + IL_0471: ldc.r8 7. + IL_047a: ldc.r8 2. + IL_0483: ldc.r8 0.0 + IL_048c: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_0491: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_049e: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0496: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04a3: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_049b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04a8: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04a0: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04ad: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04a5: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04b2: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04aa: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04b7: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04af: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04bc: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04b4: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04c1: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04b9: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04c6: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_04be: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_04cb: dup - IL_04cc: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::numbers2@99 - IL_04d1: stloc.s numbers2 - IL_04d3: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_04d8: stloc.s V_44 - IL_04da: ldloc.s V_44 - IL_04dc: stloc.s V_45 - IL_04de: ldnull - IL_04df: ldc.i4.0 - IL_04e0: ldc.r8 0.0 - IL_04e9: newobj instance void Linq101Aggregates01/averageNum@100::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, + IL_04c3: dup + IL_04c4: stsfld class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 ''.$Linq101Aggregates01::numbers2@99 + IL_04c9: stloc.s numbers2 + IL_04cb: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_04d0: stloc.s V_44 + IL_04d2: ldloc.s V_44 + IL_04d4: stloc.s V_45 + IL_04d6: ldnull + IL_04d7: ldc.i4.0 + IL_04d8: ldc.r8 0.0 + IL_04e1: newobj instance void Linq101Aggregates01/averageNum@100::.ctor(class [mscorlib]System.Collections.Generic.IEnumerator`1, int32, float64) - IL_04ee: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_04f3: stloc.s V_46 - IL_04f5: ldsfld class Linq101Aggregates01/'averageNum@100-1' Linq101Aggregates01/'averageNum@100-1'::@_instance - IL_04fa: stloc.s V_47 - IL_04fc: ldloc.s V_46 - IL_04fe: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() - IL_0503: stloc.s V_48 - IL_0505: ldloc.s V_48 - IL_0507: box class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_050c: brfalse.s IL_0510 - - IL_050e: br.s IL_051b + IL_04e6: newobj instance void class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::.ctor(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_04eb: stloc.s V_46 + IL_04ed: ldsfld class Linq101Aggregates01/'averageNum@100-1' Linq101Aggregates01/'averageNum@100-1'::@_instance + IL_04f2: stloc.s V_47 + IL_04f4: ldloc.s V_46 + IL_04f6: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2::get_Source() + IL_04fb: stloc.s V_48 + IL_04fd: ldloc.s V_48 + IL_04ff: box class [mscorlib]System.Collections.Generic.IEnumerable`1 + IL_0504: brtrue.s IL_0511 .line 100001,100001 : 0,0 '' - IL_0510: ldstr "source" - IL_0515: newobj instance void [netstandard]System.ArgumentNullException::.ctor(string) - IL_051a: throw + IL_0506: ldstr "source" + IL_050b: newobj instance void [netstandard]System.ArgumentNullException::.ctor(string) + IL_0510: throw .line 100001,100001 : 0,0 '' - IL_051b: nop - IL_051c: ldloc.s V_48 - IL_051e: callvirt instance class [netstandard]System.Collections.Generic.IEnumerator`1 class [netstandard]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_0523: stloc.s V_49 + IL_0511: nop + IL_0512: ldloc.s V_48 + IL_0514: callvirt instance class [netstandard]System.Collections.Generic.IEnumerator`1 class [netstandard]System.Collections.Generic.IEnumerable`1::GetEnumerator() + IL_0519: stloc.s V_49 .try { - IL_0525: ldc.r8 0.0 - IL_052e: stloc.s V_51 - IL_0530: ldc.i4.0 - IL_0531: stloc.s V_52 - IL_0533: ldloc.s V_49 - IL_0535: callvirt instance bool [netstandard]System.Collections.IEnumerator::MoveNext() - IL_053a: brfalse.s IL_0558 - - IL_053c: ldloc.s V_51 - IL_053e: ldloc.s V_47 - IL_0540: ldloc.s V_49 - IL_0542: callvirt instance !0 class [netstandard]System.Collections.Generic.IEnumerator`1::get_Current() - IL_0547: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_054c: add - IL_054d: stloc.s V_51 + IL_051b: ldc.r8 0.0 + IL_0524: stloc.s V_51 + IL_0526: ldc.i4.0 + IL_0527: stloc.s V_52 + IL_0529: ldloc.s V_49 + IL_052b: callvirt instance bool [netstandard]System.Collections.IEnumerator::MoveNext() + IL_0530: brfalse.s IL_054e + + IL_0532: ldloc.s V_51 + IL_0534: ldloc.s V_47 + IL_0536: ldloc.s V_49 + IL_0538: callvirt instance !0 class [netstandard]System.Collections.Generic.IEnumerator`1::get_Current() + IL_053d: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0542: add + IL_0543: stloc.s V_51 .line 100,100 : 47,58 '' - IL_054f: ldloc.s V_52 - IL_0551: ldc.i4.1 - IL_0552: add - IL_0553: stloc.s V_52 + IL_0545: ldloc.s V_52 + IL_0547: ldc.i4.1 + IL_0548: add + IL_0549: stloc.s V_52 .line 100001,100001 : 0,0 '' - IL_0555: nop - IL_0556: br.s IL_0533 + IL_054b: nop + IL_054c: br.s IL_0529 - IL_0558: ldloc.s V_52 - IL_055a: brtrue.s IL_0567 + IL_054e: ldloc.s V_52 + IL_0550: brtrue.s IL_055d .line 100001,100001 : 0,0 '' - IL_055c: ldstr "source" - IL_0561: newobj instance void [netstandard]System.InvalidOperationException::.ctor(string) - IL_0566: throw + IL_0552: ldstr "source" + IL_0557: newobj instance void [netstandard]System.InvalidOperationException::.ctor(string) + IL_055c: throw .line 100001,100001 : 0,0 '' - IL_0567: nop - IL_0568: ldloc.s V_51 - IL_056a: stloc.s V_53 - IL_056c: ldloc.s V_52 - IL_056e: stloc.s V_54 - IL_0570: ldloc.s V_53 - IL_0572: ldloc.s V_54 - IL_0574: conv.r8 - IL_0575: div - IL_0576: stloc.s V_50 - IL_0578: leave.s IL_0594 + IL_055d: nop + IL_055e: ldloc.s V_51 + IL_0560: stloc.s V_53 + IL_0562: ldloc.s V_52 + IL_0564: stloc.s V_54 + IL_0566: ldloc.s V_53 + IL_0568: ldloc.s V_54 + IL_056a: conv.r8 + IL_056b: div + IL_056c: stloc.s V_50 + IL_056e: leave.s IL_0586 } // end .try finally { - IL_057a: ldloc.s V_49 - IL_057c: isinst [mscorlib]System.IDisposable - IL_0581: stloc.s V_55 - IL_0583: ldloc.s V_55 - IL_0585: brfalse.s IL_0591 + IL_0570: ldloc.s V_49 + IL_0572: isinst [mscorlib]System.IDisposable + IL_0577: stloc.s V_55 + IL_0579: ldloc.s V_55 + IL_057b: brfalse.s IL_0585 .line 100001,100001 : 0,0 '' - IL_0587: ldloc.s V_55 - IL_0589: callvirt instance void [netstandard]System.IDisposable::Dispose() - IL_058e: ldnull - IL_058f: pop - IL_0590: endfinally + IL_057d: ldloc.s V_55 + IL_057f: callvirt instance void [netstandard]System.IDisposable::Dispose() + IL_0584: endfinally .line 100001,100001 : 0,0 '' - IL_0591: ldnull - IL_0592: pop - IL_0593: endfinally + IL_0585: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_0594: ldloc.s V_50 - IL_0596: dup - IL_0597: stsfld float64 ''.$Linq101Aggregates01::averageNum@100 - IL_059c: stloc.s averageNum - IL_059e: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_05a3: stloc.s V_56 - IL_05a5: ldloc.s V_56 - IL_05a7: stloc.s V_57 + IL_0586: ldloc.s V_50 + IL_0588: dup + IL_0589: stsfld float64 ''.$Linq101Aggregates01::averageNum@100 + IL_058e: stloc.s averageNum + IL_0590: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_0595: stloc.s V_56 + IL_0597: ldloc.s V_56 + IL_0599: stloc.s V_57 + IL_059b: ldloc.s V_56 + IL_059d: ldloc.s V_56 + IL_059f: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_words() + IL_05a4: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) IL_05a9: ldloc.s V_56 - IL_05ab: ldloc.s V_56 - IL_05ad: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_words() - IL_05b2: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_05b7: ldloc.s V_56 - IL_05b9: newobj instance void Linq101Aggregates01/averageLength@105::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_05be: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_05ab: newobj instance void Linq101Aggregates01/averageLength@105::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_05b0: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_05c3: stloc.s V_58 - IL_05c5: ldsfld class Linq101Aggregates01/'averageLength@107-1' Linq101Aggregates01/'averageLength@107-1'::@_instance - IL_05ca: stloc.s V_59 - IL_05cc: ldloc.s V_58 - IL_05ce: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_05d3: stloc.s V_60 - IL_05d5: ldloc.s V_60 - IL_05d7: box class [mscorlib]System.Collections.Generic.IEnumerable`1> - IL_05dc: brfalse.s IL_05e0 - - IL_05de: br.s IL_05eb + IL_05b5: stloc.s V_58 + IL_05b7: ldsfld class Linq101Aggregates01/'averageLength@107-1' Linq101Aggregates01/'averageLength@107-1'::@_instance + IL_05bc: stloc.s V_59 + IL_05be: ldloc.s V_58 + IL_05c0: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_05c5: stloc.s V_60 + IL_05c7: ldloc.s V_60 + IL_05c9: box class [mscorlib]System.Collections.Generic.IEnumerable`1> + IL_05ce: brtrue.s IL_05db .line 100001,100001 : 0,0 '' - IL_05e0: ldstr "source" - IL_05e5: newobj instance void [netstandard]System.ArgumentNullException::.ctor(string) - IL_05ea: throw + IL_05d0: ldstr "source" + IL_05d5: newobj instance void [netstandard]System.ArgumentNullException::.ctor(string) + IL_05da: throw .line 100001,100001 : 0,0 '' - IL_05eb: nop - IL_05ec: ldloc.s V_60 - IL_05ee: callvirt instance class [netstandard]System.Collections.Generic.IEnumerator`1 class [netstandard]System.Collections.Generic.IEnumerable`1>::GetEnumerator() - IL_05f3: stloc.s V_61 + IL_05db: nop + IL_05dc: ldloc.s V_60 + IL_05de: callvirt instance class [netstandard]System.Collections.Generic.IEnumerator`1 class [netstandard]System.Collections.Generic.IEnumerable`1>::GetEnumerator() + IL_05e3: stloc.s V_61 .try { - IL_05f5: ldc.r8 0.0 - IL_05fe: stloc.s V_63 - IL_0600: ldc.i4.0 - IL_0601: stloc.s V_64 - IL_0603: ldloc.s V_61 - IL_0605: callvirt instance bool [netstandard]System.Collections.IEnumerator::MoveNext() - IL_060a: brfalse.s IL_0628 - - IL_060c: ldloc.s V_63 - IL_060e: ldloc.s V_59 - IL_0610: ldloc.s V_61 - IL_0612: callvirt instance !0 class [netstandard]System.Collections.Generic.IEnumerator`1>::get_Current() - IL_0617: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>::Invoke(!0) - IL_061c: add - IL_061d: stloc.s V_63 + IL_05e5: ldc.r8 0.0 + IL_05ee: stloc.s V_63 + IL_05f0: ldc.i4.0 + IL_05f1: stloc.s V_64 + IL_05f3: ldloc.s V_61 + IL_05f5: callvirt instance bool [netstandard]System.Collections.IEnumerator::MoveNext() + IL_05fa: brfalse.s IL_0618 + + IL_05fc: ldloc.s V_63 + IL_05fe: ldloc.s V_59 + IL_0600: ldloc.s V_61 + IL_0602: callvirt instance !0 class [netstandard]System.Collections.Generic.IEnumerator`1>::get_Current() + IL_0607: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,float64>::Invoke(!0) + IL_060c: add + IL_060d: stloc.s V_63 .line 107,107 : 9,21 '' - IL_061f: ldloc.s V_64 - IL_0621: ldc.i4.1 - IL_0622: add - IL_0623: stloc.s V_64 + IL_060f: ldloc.s V_64 + IL_0611: ldc.i4.1 + IL_0612: add + IL_0613: stloc.s V_64 .line 100001,100001 : 0,0 '' - IL_0625: nop - IL_0626: br.s IL_0603 + IL_0615: nop + IL_0616: br.s IL_05f3 - IL_0628: ldloc.s V_64 - IL_062a: brtrue.s IL_0637 + IL_0618: ldloc.s V_64 + IL_061a: brtrue.s IL_0627 .line 100001,100001 : 0,0 '' - IL_062c: ldstr "source" - IL_0631: newobj instance void [netstandard]System.InvalidOperationException::.ctor(string) - IL_0636: throw + IL_061c: ldstr "source" + IL_0621: newobj instance void [netstandard]System.InvalidOperationException::.ctor(string) + IL_0626: throw .line 100001,100001 : 0,0 '' - IL_0637: nop - IL_0638: ldloc.s V_63 - IL_063a: stloc.s V_65 - IL_063c: ldloc.s V_64 - IL_063e: stloc.s V_66 - IL_0640: ldloc.s V_65 - IL_0642: ldloc.s V_66 - IL_0644: conv.r8 - IL_0645: div - IL_0646: stloc.s V_62 - IL_0648: leave.s IL_0664 + IL_0627: nop + IL_0628: ldloc.s V_63 + IL_062a: stloc.s V_65 + IL_062c: ldloc.s V_64 + IL_062e: stloc.s V_66 + IL_0630: ldloc.s V_65 + IL_0632: ldloc.s V_66 + IL_0634: conv.r8 + IL_0635: div + IL_0636: stloc.s V_62 + IL_0638: leave.s IL_0650 } // end .try finally { - IL_064a: ldloc.s V_61 - IL_064c: isinst [mscorlib]System.IDisposable - IL_0651: stloc.s V_67 - IL_0653: ldloc.s V_67 - IL_0655: brfalse.s IL_0661 + IL_063a: ldloc.s V_61 + IL_063c: isinst [mscorlib]System.IDisposable + IL_0641: stloc.s V_67 + IL_0643: ldloc.s V_67 + IL_0645: brfalse.s IL_064f .line 100001,100001 : 0,0 '' - IL_0657: ldloc.s V_67 - IL_0659: callvirt instance void [netstandard]System.IDisposable::Dispose() - IL_065e: ldnull - IL_065f: pop - IL_0660: endfinally + IL_0647: ldloc.s V_67 + IL_0649: callvirt instance void [netstandard]System.IDisposable::Dispose() + IL_064e: endfinally .line 100001,100001 : 0,0 '' - IL_0661: ldnull - IL_0662: pop - IL_0663: endfinally + IL_064f: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_0664: ldloc.s V_62 - IL_0666: dup - IL_0667: stsfld float64 ''.$Linq101Aggregates01::averageLength@103 - IL_066c: stloc.s averageLength + IL_0650: ldloc.s V_62 + IL_0652: dup + IL_0653: stsfld float64 ''.$Linq101Aggregates01::averageLength@103 + IL_0658: stloc.s averageLength .line 111,117 : 1,21 '' - IL_066e: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() - IL_0673: stloc.s V_68 + IL_065a: call class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_query() + IL_065f: stloc.s V_68 + IL_0661: ldloc.s V_68 + IL_0663: ldloc.s V_68 + IL_0665: ldloc.s V_68 + IL_0667: ldloc.s V_68 + IL_0669: ldloc.s V_68 + IL_066b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() + IL_0670: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) IL_0675: ldloc.s V_68 - IL_0677: ldloc.s V_68 - IL_0679: ldloc.s V_68 - IL_067b: ldloc.s V_68 - IL_067d: ldloc.s V_68 - IL_067f: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 Linq101Aggregates01::get_products() - IL_0684: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Source(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_0689: ldloc.s V_68 - IL_068b: newobj instance void Linq101Aggregates01/categories6@113::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_0690: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0677: newobj instance void Linq101Aggregates01/categories6@113::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_067c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0695: ldsfld class Linq101Aggregates01/'categories6@114-1' Linq101Aggregates01/'categories6@114-1'::@_instance - IL_069a: ldsfld class Linq101Aggregates01/'categories6@114-2' Linq101Aggregates01/'categories6@114-2'::@_instance - IL_069f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0681: ldsfld class Linq101Aggregates01/'categories6@114-1' Linq101Aggregates01/'categories6@114-1'::@_instance + IL_0686: ldsfld class Linq101Aggregates01/'categories6@114-2' Linq101Aggregates01/'categories6@114-2'::@_instance + IL_068b: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,!!3> [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::GroupValBy(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_06a4: ldloc.s V_68 - IL_06a6: newobj instance void Linq101Aggregates01/'categories6@114-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) - IL_06ab: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_0690: ldloc.s V_68 + IL_0692: newobj instance void Linq101Aggregates01/'categories6@114-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder) + IL_0697: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::For,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2,valuetype [mscorlib]System.Decimal>,object>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_06b0: ldsfld class Linq101Aggregates01/'categories6@116-4' Linq101Aggregates01/'categories6@116-4'::@_instance - IL_06b5: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, + IL_069c: ldsfld class Linq101Aggregates01/'categories6@116-4' Linq101Aggregates01/'categories6@116-4'::@_instance + IL_06a1: callvirt instance class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2 [FSharp.Core]Microsoft.FSharp.Linq.QueryBuilder::Select,valuetype [mscorlib]System.Decimal>,class [mscorlib]System.Collections.IEnumerable,class [mscorlib]System.Tuple`2>(class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_06ba: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() - IL_06bf: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) - IL_06c4: dup - IL_06c5: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories6@111 - IL_06ca: stloc.s categories6 - IL_06cc: ret + IL_06a6: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerable`1 class [FSharp.Core]Microsoft.FSharp.Linq.QuerySource`2,class [mscorlib]System.Collections.IEnumerable>::get_Source() + IL_06ab: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToArray>(class [mscorlib]System.Collections.Generic.IEnumerable`1) + IL_06b0: dup + IL_06b1: stsfld class [mscorlib]System.Tuple`2[] ''.$Linq101Aggregates01::categories6@111 + IL_06b6: stloc.s categories6 + IL_06b8: ret } // end of method $Linq101Aggregates01::main@ } // end of class ''.$Linq101Aggregates01 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101ElementOperators01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101ElementOperators01.il.bsl index 02306b555d2..327debf86ce 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101ElementOperators01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101ElementOperators01.il.bsl @@ -45,13 +45,13 @@ // Offset: 0x00000388 Length: 0x00000127 } .module Linq101ElementOperators01.exe -// MVID: {60B78A59-19D7-C20D-A745-0383598AB760} +// MVID: {60BD414C-19D7-C20D-A745-03834C41BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x09100000 +// Image base: 0x008A0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -189,11 +189,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101ElementOperators01/products12@12::pc @@ -205,7 +204,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -255,41 +254,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [Utils]Utils/Product Linq101ElementOperators01/products12@12::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 12,12 : 9,29 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method products12@12::Close .method public strict virtual instance bool @@ -534,11 +526,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101ElementOperators01/startsWithO@22::pc @@ -550,7 +541,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -600,41 +591,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101ElementOperators01/startsWithO@22::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 22,22 : 9,28 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method startsWithO@22::Close .method public strict virtual instance bool @@ -880,11 +864,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101ElementOperators01/firstNumOrDefault@31::pc @@ -896,7 +879,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -946,41 +929,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101ElementOperators01/firstNumOrDefault@31::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 31,31 : 9,28 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method firstNumOrDefault@31::Close .method public strict virtual instance bool @@ -1184,11 +1160,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101ElementOperators01/fourthLowNum@52::pc @@ -1200,7 +1175,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -1250,41 +1225,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101ElementOperators01/fourthLowNum@52::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 52,52 : 9,29 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method fourthLowNum@52::Close .method public strict virtual instance bool diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Grouping01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Grouping01.il.bsl index 38346254e8f..3a62a0db54e 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Grouping01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Grouping01.il.bsl @@ -50,7 +50,7 @@ // Offset: 0x00000408 Length: 0x00000129 } .module Linq101Grouping01.exe -// MVID: {60D46F1F-FB79-E5BF-A745-03831F6FD460} +// MVID: {60BCC37C-FB79-E5BF-A745-03837CC3BC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Joins01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Joins01.il.bsl index 7078d4c3e68..0f1a446e98d 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Joins01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Joins01.il.bsl @@ -45,13 +45,13 @@ // Offset: 0x00000310 Length: 0x000000C3 } .module Linq101Joins01.exe -// MVID: {60B78A59-151B-685E-A745-0383598AB760} +// MVID: {60BCC37C-151B-685E-A745-03837CC3BC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06AF0000 +// Image base: 0x059A0000 // =============== CLASS MEMBERS DECLARATION =================== diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Ordering01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Ordering01.il.bsl index abcadfd0493..1d41a07ed66 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Ordering01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Ordering01.il.bsl @@ -40,13 +40,13 @@ // Offset: 0x000003B8 Length: 0x00000134 } .module Linq101Ordering01.exe -// MVID: {60B78A59-649A-6956-A745-0383598AB760} +// MVID: {60BD414C-649A-6956-A745-03834C41BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x09540000 +// Image base: 0x053F0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -184,11 +184,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Ordering01/sortedWords@11::pc @@ -200,7 +199,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -250,41 +249,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101Ordering01/sortedWords@11::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 11,11 : 9,26 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method sortedWords@11::Close .method public strict virtual instance bool @@ -526,11 +518,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Ordering01/sortedWords2@18::pc @@ -542,7 +533,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -592,41 +583,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101Ordering01/sortedWords2@18::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 18,18 : 9,26 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method sortedWords2@18::Close .method public strict virtual instance bool @@ -989,11 +973,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Ordering01/sortedProducts2@44::pc @@ -1005,7 +988,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -1055,41 +1038,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [Utils]Utils/Product Linq101Ordering01/sortedProducts2@44::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 44,44 : 9,29 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method sortedProducts2@44::Close .method public strict virtual instance bool @@ -1333,11 +1309,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Ordering01/sortedDigits@52::pc @@ -1349,7 +1324,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -1399,41 +1374,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101Ordering01/sortedDigits@52::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 52,52 : 9,27 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method sortedDigits@52::Close .method public strict virtual instance bool diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Partitioning01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Partitioning01.il.bsl index e6988e57bd7..10ba7c88ae0 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Partitioning01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Partitioning01.il.bsl @@ -45,13 +45,13 @@ // Offset: 0x000003D8 Length: 0x00000138 } .module Linq101Partitioning01.exe -// MVID: {60B78A59-B280-A6A2-A745-0383598AB760} +// MVID: {60BD414C-B280-A6A2-A745-03834C41BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x069E0000 +// Image base: 0x04E00000 // =============== CLASS MEMBERS DECLARATION =================== @@ -189,11 +189,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Partitioning01/first3Numbers@12::pc @@ -205,7 +204,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -255,41 +254,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101Partitioning01/first3Numbers@12::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 12,12 : 9,28 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method first3Numbers@12::Close .method public strict virtual instance bool @@ -702,11 +694,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Partitioning01/allButFirst4Numbers@29::pc @@ -718,7 +709,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -768,41 +759,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101Partitioning01/allButFirst4Numbers@29::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 29,29 : 9,28 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method allButFirst4Numbers@29::Close .method public strict virtual instance bool @@ -1215,11 +1199,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Partitioning01/firstNumbersLessThan6@45::pc @@ -1231,7 +1214,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -1281,41 +1264,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101Partitioning01/firstNumbersLessThan6@45::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 45,45 : 9,28 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method firstNumbersLessThan6@45::Close .method public strict virtual instance bool @@ -1559,11 +1535,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Partitioning01/allButFirst3Numbers@52::pc @@ -1575,7 +1550,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -1625,41 +1600,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101Partitioning01/allButFirst3Numbers@52::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 52,52 : 9,28 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method allButFirst3Numbers@52::Close .method public strict virtual instance bool diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Quantifiers01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Quantifiers01.il.bsl index 2341c4243cf..de229a97c43 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Quantifiers01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Quantifiers01.il.bsl @@ -45,13 +45,13 @@ // Offset: 0x00000398 Length: 0x000000FF } .module Linq101Quantifiers01.exe -// MVID: {60B78A59-76DD-E373-A745-0383598AB760} +// MVID: {60BD414C-76DD-E373-A745-03834C41BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x065D0000 +// Image base: 0x07320000 // =============== CLASS MEMBERS DECLARATION =================== @@ -189,11 +189,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Quantifiers01/iAfterE@12::pc @@ -205,7 +204,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -255,41 +254,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101Quantifiers01/iAfterE@12::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 12,12 : 9,26 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method iAfterE@12::Close .method public strict virtual instance bool @@ -798,11 +790,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Quantifiers01/onlyOdd@32::pc @@ -814,7 +805,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -864,41 +855,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101Quantifiers01/onlyOdd@32::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 32,32 : 9,28 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method onlyOdd@32::Close .method public strict virtual instance bool diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Select01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Select01.il.bsl index 27bc8c410f8..719b62b9b9a 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Select01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Select01.il.bsl @@ -45,13 +45,13 @@ // Offset: 0x00000648 Length: 0x00000204 } .module Linq101Select01.exe -// MVID: {60B78A59-6057-8F80-A745-0383598AB760} +// MVID: {60BD414C-6057-8F80-A745-03834C41BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x07170000 +// Image base: 0x06DA0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -234,11 +234,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Select01/numsPlusOne@13::pc @@ -250,7 +249,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -300,41 +299,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101Select01/numsPlusOne@13::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 13,13 : 9,23 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method numsPlusOne@13::Close .method public strict virtual instance bool @@ -582,11 +574,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Select01/productNames@22::pc @@ -598,7 +589,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -648,41 +639,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101Select01/productNames@22::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 22,22 : 9,31 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method productNames@22::Close .method public strict virtual instance bool @@ -931,11 +915,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Select01/textNums@30::pc @@ -947,7 +930,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -997,41 +980,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101Select01/textNums@30::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 30,30 : 9,29 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method textNums@30::Close .method public strict virtual instance bool @@ -1283,11 +1259,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Select01/upperLowerWords@39::pc @@ -1299,7 +1274,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -1349,41 +1324,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [mscorlib]System.Tuple`2 Linq101Select01/upperLowerWords@39::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 39,39 : 8,41 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method upperLowerWords@39::Close .method public strict virtual instance bool @@ -1639,11 +1607,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Select01/digitOddEvens@46::pc @@ -1655,7 +1622,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -1705,41 +1672,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [mscorlib]System.Tuple`2 Linq101Select01/digitOddEvens@46::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 46,46 : 9,42 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method digitOddEvens@46::Close .method public strict virtual instance bool @@ -1994,11 +1954,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Select01/productInfos@53::pc @@ -2010,7 +1969,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -2060,41 +2019,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld class [mscorlib]System.Tuple`3 Linq101Select01/productInfos@53::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 53,53 : 9,56 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method productInfos@53::Close .method public strict virtual instance bool diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101SetOperators01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101SetOperators01.il.bsl index baba5ea96e7..6b0fad731d3 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101SetOperators01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101SetOperators01.il.bsl @@ -189,11 +189,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101SetOperators01/uniqueFactors@13::pc @@ -205,7 +204,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -255,41 +254,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld int32 Linq101SetOperators01/uniqueFactors@13::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 13,13 : 9,33 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method uniqueFactors@13::Close .method public strict virtual instance bool @@ -537,11 +529,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101SetOperators01/categoryNames@23::pc @@ -553,7 +544,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -603,41 +594,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101SetOperators01/categoryNames@23::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 23,23 : 9,26 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method categoryNames@23::Close .method public strict virtual instance bool @@ -887,11 +871,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101SetOperators01/productFirstChars@33::pc @@ -903,7 +886,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -953,41 +936,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld char Linq101SetOperators01/productFirstChars@33::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 33,33 : 9,33 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method productFirstChars@33::Close .method public strict virtual instance bool @@ -1237,11 +1213,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101SetOperators01/customerFirstChars@39::pc @@ -1253,7 +1228,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -1303,41 +1278,34 @@ IL_005d: ldarg.0 IL_005e: ldc.i4.0 IL_005f: stfld char Linq101SetOperators01/customerFirstChars@39::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 39,39 : 9,33 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method customerFirstChars@39::Close .method public strict virtual instance bool diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Where01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Where01.il.bsl index b60623e8746..600f06b3b29 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Where01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/QueryExpressionStepping/Linq101Where01.il.bsl @@ -45,13 +45,13 @@ // Offset: 0x000003D0 Length: 0x0000012E } .module Linq101Where01.exe -// MVID: {60B78A59-FF23-CD21-A745-0383598AB760} +// MVID: {60BD414C-FF23-CD21-A745-03834C41BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06550000 +// Image base: 0x05350000 // =============== CLASS MEMBERS DECLARATION =================== @@ -826,11 +826,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 133 (0x85) + // Code size 127 (0x7f) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 Linq101Where01/'shortDigits@52-2'::pc @@ -842,7 +841,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br.s IL_007c + IL_0014: br.s IL_0076 .line 100001,100001 : 0,0 '' IL_0016: nop @@ -892,41 +891,34 @@ IL_005d: ldarg.0 IL_005e: ldnull IL_005f: stfld string Linq101Where01/'shortDigits@52-2'::current - IL_0064: ldnull - IL_0065: stloc.1 - IL_0066: leave.s IL_0074 + IL_0064: leave.s IL_0070 } // end .try catch [mscorlib]System.Object { - IL_0068: castclass [mscorlib]System.Exception - IL_006d: stloc.2 + IL_0066: castclass [mscorlib]System.Exception + IL_006b: stloc.1 .line 52,52 : 9,17 '' - IL_006e: ldloc.2 - IL_006f: stloc.0 - IL_0070: ldnull - IL_0071: stloc.1 - IL_0072: leave.s IL_0074 + IL_006c: ldloc.1 + IL_006d: stloc.0 + IL_006e: leave.s IL_0070 .line 100001,100001 : 0,0 '' } // end handler - IL_0074: ldloc.1 - IL_0075: pop - .line 100001,100001 : 0,0 '' - IL_0076: nop - IL_0077: br IL_0000 + IL_0070: nop + IL_0071: br IL_0000 - IL_007c: ldloc.0 - IL_007d: ldnull - IL_007e: cgt.un - IL_0080: brfalse.s IL_0084 + IL_0076: ldloc.0 + IL_0077: ldnull + IL_0078: cgt.un + IL_007a: brfalse.s IL_007e .line 100001,100001 : 0,0 '' - IL_0082: ldloc.0 - IL_0083: throw + IL_007c: ldloc.0 + IL_007d: throw .line 100001,100001 : 0,0 '' - IL_0084: ret + IL_007e: ret } // end of method 'shortDigits@52-2'::Close .method public strict virtual instance bool diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest5.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest5.il.bsl index a3ce205c086..0d7bed5355a 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest5.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest5.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000268 Length: 0x000000AD } .module SeqExpressionSteppingTest5.exe -// MVID: {60B78A59-2432-9401-A745-0383598AB760} +// MVID: {60BD414C-2432-9401-A745-03834C41BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x05A80000 +// Image base: 0x05410000 // =============== CLASS MEMBERS DECLARATION =================== @@ -212,11 +212,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 162 (0xa2) + // Code size 156 (0x9c) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 SeqExpressionSteppingTest5/SeqExpressionSteppingTest5/f4@5::pc @@ -228,7 +227,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br IL_0099 + IL_0014: br IL_0093 .line 100001,100001 : 0,0 '' IL_0019: nop @@ -293,41 +292,34 @@ IL_007a: ldarg.0 IL_007b: ldc.i4.0 IL_007c: stfld int32 SeqExpressionSteppingTest5/SeqExpressionSteppingTest5/f4@5::current - IL_0081: ldnull - IL_0082: stloc.1 - IL_0083: leave.s IL_0091 + IL_0081: leave.s IL_008d } // end .try catch [mscorlib]System.Object { - IL_0085: castclass [mscorlib]System.Exception - IL_008a: stloc.2 + IL_0083: castclass [mscorlib]System.Exception + IL_0088: stloc.1 .line 5,5 : 19,20 '' - IL_008b: ldloc.2 - IL_008c: stloc.0 - IL_008d: ldnull - IL_008e: stloc.1 - IL_008f: leave.s IL_0091 + IL_0089: ldloc.1 + IL_008a: stloc.0 + IL_008b: leave.s IL_008d .line 100001,100001 : 0,0 '' } // end handler - IL_0091: ldloc.1 - IL_0092: pop - .line 100001,100001 : 0,0 '' - IL_0093: nop - IL_0094: br IL_0000 + IL_008d: nop + IL_008e: br IL_0000 - IL_0099: ldloc.0 - IL_009a: ldnull - IL_009b: cgt.un - IL_009d: brfalse.s IL_00a1 + IL_0093: ldloc.0 + IL_0094: ldnull + IL_0095: cgt.un + IL_0097: brfalse.s IL_009b .line 100001,100001 : 0,0 '' - IL_009f: ldloc.0 - IL_00a0: throw + IL_0099: ldloc.0 + IL_009a: throw .line 100001,100001 : 0,0 '' - IL_00a1: ret + IL_009b: ret } // end of method f4@5::Close .method public strict virtual instance bool diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest6.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest6.il.bsl index 75fbbcc82e7..f12c4966743 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest6.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest6.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x000002A0 Length: 0x000000BA } .module SeqExpressionSteppingTest6.exe -// MVID: {60B78A59-2432-94A2-A745-0383598AB760} +// MVID: {60BD414C-2432-94A2-A745-03834C41BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06B30000 +// Image base: 0x06E80000 // =============== CLASS MEMBERS DECLARATION =================== @@ -254,11 +254,10 @@ .method public strict virtual instance void Close() cil managed { - // Code size 173 (0xad) + // Code size 167 (0xa7) .maxstack 6 .locals init ([0] class [mscorlib]System.Exception V_0, - [1] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_1, - [2] class [mscorlib]System.Exception e) + [1] class [mscorlib]System.Exception e) .line 100001,100001 : 0,0 '' IL_0000: ldarg.0 IL_0001: ldfld int32 SeqExpressionSteppingTest6/SeqExpressionSteppingTest6/f7@6::pc @@ -270,7 +269,7 @@ .line 100001,100001 : 0,0 '' IL_0013: nop - IL_0014: br IL_00a4 + IL_0014: br IL_009e .line 100001,100001 : 0,0 '' IL_0019: nop @@ -343,41 +342,34 @@ IL_0085: ldarg.0 IL_0086: ldc.i4.0 IL_0087: stfld int32 SeqExpressionSteppingTest6/SeqExpressionSteppingTest6/f7@6::current - IL_008c: ldnull - IL_008d: stloc.1 - IL_008e: leave.s IL_009c + IL_008c: leave.s IL_0098 } // end .try catch [mscorlib]System.Object { - IL_0090: castclass [mscorlib]System.Exception - IL_0095: stloc.2 + IL_008e: castclass [mscorlib]System.Exception + IL_0093: stloc.1 .line 6,8 : 15,25 '' - IL_0096: ldloc.2 - IL_0097: stloc.0 - IL_0098: ldnull - IL_0099: stloc.1 - IL_009a: leave.s IL_009c + IL_0094: ldloc.1 + IL_0095: stloc.0 + IL_0096: leave.s IL_0098 .line 100001,100001 : 0,0 '' } // end handler - IL_009c: ldloc.1 - IL_009d: pop - .line 100001,100001 : 0,0 '' - IL_009e: nop - IL_009f: br IL_0000 + IL_0098: nop + IL_0099: br IL_0000 - IL_00a4: ldloc.0 - IL_00a5: ldnull - IL_00a6: cgt.un - IL_00a8: brfalse.s IL_00ac + IL_009e: ldloc.0 + IL_009f: ldnull + IL_00a0: cgt.un + IL_00a2: brfalse.s IL_00a6 .line 100001,100001 : 0,0 '' - IL_00aa: ldloc.0 - IL_00ab: throw + IL_00a4: ldloc.0 + IL_00a5: throw .line 100001,100001 : 0,0 '' - IL_00ac: ret + IL_00a6: ret } // end of method f7@6::Close .method public strict virtual instance bool diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest7.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest7.il.bsl index a193421655c..4427341eb37 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest7.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionStepping/SeqExpressionSteppingTest7.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000270 Length: 0x00000098 } .module SeqExpressionSteppingTest7.exe -// MVID: {60B78A59-2432-93C3-A745-0383598AB760} +// MVID: {60BCC37C-2432-93C3-A745-03837CC3BC60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x054A0000 +// Image base: 0x05980000 // =============== CLASS MEMBERS DECLARATION =================== @@ -127,14 +127,13 @@ .method public static void main@() cil managed { .entrypoint - // Code size 103 (0x67) + // Code size 98 (0x62) .maxstack 4 .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 r, [1] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> V_1, [2] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_2, - [3] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_3, - [4] class [mscorlib]System.Exception V_4, - [5] class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_5) + [3] class [mscorlib]System.Exception V_3, + [4] class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_4) .line 4,4 : 1,14 '' IL_0000: ldc.i4.0 IL_0001: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::Ref(!!0) @@ -145,53 +144,50 @@ IL_000d: ldstr "res = %A" IL_0012: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit>,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>::.ctor(string) IL_0017: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_001c: stloc.1 .line 6,6 : 21,24 '' + IL_001c: stloc.1 + .line 6,6 : 25,29 '' .try { - IL_001d: nop - .line 6,6 : 25,29 '' - IL_001e: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 SeqExpressionSteppingTest7::f() - IL_0023: stloc.3 - IL_0024: leave.s IL_005c + IL_001d: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 SeqExpressionSteppingTest7::f() + IL_0022: stloc.2 + IL_0023: leave.s IL_0059 .line 6,6 : 30,34 '' } // end .try catch [mscorlib]System.Object { - IL_0026: castclass [mscorlib]System.Exception - IL_002b: stloc.s V_4 - IL_002d: ldloc.s V_4 - IL_002f: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::FailurePattern(class [mscorlib]System.Exception) - IL_0034: stloc.s V_5 - IL_0036: ldloc.s V_5 - IL_0038: brfalse.s IL_0051 + IL_0025: castclass [mscorlib]System.Exception + IL_002a: stloc.3 + IL_002b: ldloc.3 + IL_002c: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::FailurePattern(class [mscorlib]System.Exception) + IL_0031: stloc.s V_4 + IL_0033: ldloc.s V_4 + IL_0035: brfalse.s IL_004e .line 6,6 : 48,52 '' - IL_003a: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 SeqExpressionSteppingTest7::get_r() - IL_003f: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::op_Dereference(class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1) - IL_0044: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() - IL_0049: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, + IL_0037: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 SeqExpressionSteppingTest7::get_r() + IL_003c: call !!0 [FSharp.Core]Microsoft.FSharp.Core.Operators::op_Dereference(class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1) + IL_0041: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_0046: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) - IL_004e: stloc.3 - IL_004f: leave.s IL_005c + IL_004b: stloc.2 + IL_004c: leave.s IL_0059 .line 100001,100001 : 0,0 '' - IL_0051: rethrow - IL_0053: ldnull - IL_0054: unbox.any class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 - IL_0059: stloc.3 - IL_005a: leave.s IL_005c + IL_004e: rethrow + IL_0050: ldnull + IL_0051: unbox.any class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 + IL_0056: stloc.2 + IL_0057: leave.s IL_0059 .line 100001,100001 : 0,0 '' } // end handler - IL_005c: ldloc.3 - IL_005d: stloc.2 - IL_005e: ldloc.1 - IL_005f: ldloc.2 - IL_0060: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0) - IL_0065: pop - IL_0066: ret + IL_0059: ldloc.1 + IL_005a: ldloc.2 + IL_005b: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0) + IL_0060: pop + IL_0061: ret } // end of method $SeqExpressionSteppingTest7::main@ } // end of class ''.$SeqExpressionSteppingTest7 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionTailCalls/SeqExpressionTailCalls01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionTailCalls/SeqExpressionTailCalls01.il.bsl index 79a56d68ab0..94df7654a1d 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionTailCalls/SeqExpressionTailCalls01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionTailCalls/SeqExpressionTailCalls01.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000220 Length: 0x0000008C } .module SeqExpressionTailCalls01.exe -// MVID: {60B78A58-093A-A6BE-A745-0383588AB760} +// MVID: {60BD414B-093A-A6BE-A745-03834B41BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06850000 +// Image base: 0x06CE0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -130,7 +130,6 @@ IL_003a: ldarg.0 IL_003b: ldc.i4.2 IL_003c: stfld int32 SeqExpressionTailCalls01/rwalk@3::pc - .line 3,3 : 41,52 '' IL_0041: ldarg.1 IL_0042: ldarg.0 IL_0043: ldfld int32 SeqExpressionTailCalls01/rwalk@3::x diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionTailCalls/SeqExpressionTailCalls02.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionTailCalls/SeqExpressionTailCalls02.il.bsl index 1a661c56fba..bd032aa6f46 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionTailCalls/SeqExpressionTailCalls02.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/SeqExpressionTailCalls/SeqExpressionTailCalls02.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000258 Length: 0x0000009E } .module SeqExpressionTailCalls02.exe -// MVID: {60B78A58-093A-EC43-A745-0383588AB760} +// MVID: {60BD414B-093A-EC43-A745-03834B41BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x066C0000 +// Image base: 0x06760000 // =============== CLASS MEMBERS DECLARATION =================== @@ -130,7 +130,6 @@ IL_003a: ldarg.0 IL_003b: ldc.i4.2 IL_003c: stfld int32 SeqExpressionTailCalls02/rwalk1@5::pc - .line 5,5 : 42,54 '' IL_0041: ldarg.1 IL_0042: ldarg.0 IL_0043: ldfld int32 SeqExpressionTailCalls02/rwalk1@5::x @@ -314,7 +313,6 @@ IL_003a: ldarg.0 IL_003b: ldc.i4.2 IL_003c: stfld int32 SeqExpressionTailCalls02/rwalk2@6::pc - .line 6,6 : 42,54 '' IL_0041: ldarg.1 IL_0042: ldarg.0 IL_0043: ldfld int32 SeqExpressionTailCalls02/rwalk2@6::x diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/StaticInit/LetBinding01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/StaticInit/LetBinding01.il.bsl index 5af7ea86311..849857520b5 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/StaticInit/LetBinding01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/StaticInit/LetBinding01.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x000001B8 Length: 0x00000070 } .module LetBinding01.exe -// MVID: {60B68B90-269D-BEEF-A745-0383908BB660} +// MVID: {608C050A-269D-BEEF-A745-03830A058C60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06AB0000 +// Image base: 0x066B0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -79,9 +79,8 @@ .method public static void main@() cil managed { .entrypoint - // Code size 37 (0x25) - .maxstack 4 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_0) + // Code size 33 (0x21) + .maxstack 8 .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' .line 5,5 : 1,11 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\StaticInit\\LetBinding01.fs' IL_0000: call class [FSharp.Core]Microsoft.FSharp.Core.Unit LetBinding01::get_x() @@ -90,14 +89,10 @@ IL_0006: ldstr "x = %A" IL_000b: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::.ctor(string) IL_0010: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0015: stloc.0 - IL_0016: call class [FSharp.Core]Microsoft.FSharp.Core.Unit LetBinding01::get_x() - IL_001b: pop - IL_001c: ldloc.0 - IL_001d: ldnull - IL_001e: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_0023: pop - IL_0024: ret + IL_0015: call class [FSharp.Core]Microsoft.FSharp.Core.Unit LetBinding01::get_x() + IL_001a: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_001f: pop + IL_0020: ret } // end of method $LetBinding01::main@ } // end of class ''.$LetBinding01 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction3b.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction3b.il.bsl index 80497c1223d..89eb0540914 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction3b.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction3b.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000200 Length: 0x0000008A } .module TestFunction3b.exe -// MVID: {60B68B97-A662-4FC9-A745-0383978BB660} +// MVID: {60BD473A-A662-4FC9-A745-03833A47BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x090C0000 +// Image base: 0x059B0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -75,22 +75,21 @@ .method public static void TestFunction3b() cil managed { - // Code size 69 (0x45) + // Code size 65 (0x41) .maxstack 3 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_0, - [1] int32 x, - [2] string V_2, - [3] class [mscorlib]System.Exception V_3, - [4] class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_4) + .locals init ([0] int32 x, + [1] string V_1, + [2] class [mscorlib]System.Exception V_2, + [3] class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_3) .line 11,11 : 8,31 '' .try { IL_0000: call int32 TestFunction3b::TestFunction1() - IL_0005: stloc.1 + IL_0005: stloc.0 .line 12,12 : 8,24 '' IL_0006: ldstr "hello" - IL_000b: stloc.2 - IL_000c: ldloc.2 + IL_000b: stloc.1 + IL_000c: ldloc.1 IL_000d: call class [mscorlib]System.Exception [FSharp.Core]Microsoft.FSharp.Core.Operators::Failure(string) IL_0012: throw @@ -99,32 +98,30 @@ catch [mscorlib]System.Object { IL_0013: castclass [mscorlib]System.Exception - IL_0018: stloc.3 - IL_0019: ldloc.3 + IL_0018: stloc.2 + IL_0019: ldloc.2 IL_001a: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::FailurePattern(class [mscorlib]System.Exception) - IL_001f: stloc.s V_4 - IL_0021: ldloc.s V_4 - IL_0023: brfalse.s IL_0037 + IL_001f: stloc.3 + IL_0020: ldloc.3 + IL_0021: brfalse.s IL_0035 .line 14,14 : 8,23 '' - IL_0025: ldstr "World" - IL_002a: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) - IL_002f: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0034: stloc.0 - IL_0035: leave.s IL_0042 + IL_0023: ldstr "World" + IL_0028: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_002d: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0032: pop + IL_0033: leave.s IL_0040 .line 100001,100001 : 0,0 '' - IL_0037: rethrow - IL_0039: ldnull - IL_003a: unbox.any [FSharp.Core]Microsoft.FSharp.Core.Unit - IL_003f: stloc.0 - IL_0040: leave.s IL_0042 + IL_0035: rethrow + IL_0037: ldnull + IL_0038: unbox.any [FSharp.Core]Microsoft.FSharp.Core.Unit + IL_003d: pop + IL_003e: leave.s IL_0040 .line 100001,100001 : 0,0 '' } // end handler - IL_0042: ldloc.0 - IL_0043: pop - IL_0044: ret + IL_0040: ret } // end of method TestFunction3b::TestFunction3b } // end of class TestFunction3b diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction3c.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction3c.il.bsl index aa5d2e75dc1..b30fe1df232 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction3c.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/TestFunction3c.il.bsl @@ -41,13 +41,13 @@ // Offset: 0x00000200 Length: 0x0000008A } .module TestFunction3c.exe -// MVID: {60B68B97-A662-4FAC-A745-0383978BB660} +// MVID: {60BD4158-A662-4FAC-A745-03835841BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06B00000 +// Image base: 0x06570000 // =============== CLASS MEMBERS DECLARATION =================== @@ -80,24 +80,23 @@ .method public static void TestFunction3c() cil managed { - // Code size 101 (0x65) + // Code size 95 (0x5f) .maxstack 4 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_0, - [1] int32 x, - [2] string V_2, - [3] class [mscorlib]System.Exception V_3, - [4] class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_4, - [5] string msg, - [6] string V_6) + .locals init ([0] int32 x, + [1] string V_1, + [2] class [mscorlib]System.Exception V_2, + [3] class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_3, + [4] string msg, + [5] string V_5) .line 11,11 : 8,31 '' .try { IL_0000: call int32 TestFunction3c::TestFunction1() - IL_0005: stloc.1 + IL_0005: stloc.0 .line 12,12 : 8,24 '' IL_0006: ldstr "hello" - IL_000b: stloc.2 - IL_000c: ldloc.2 + IL_000b: stloc.1 + IL_000c: ldloc.1 IL_000d: call class [mscorlib]System.Exception [FSharp.Core]Microsoft.FSharp.Core.Operators::Failure(string) IL_0012: throw @@ -106,44 +105,42 @@ catch [mscorlib]System.Object { IL_0013: castclass [mscorlib]System.Exception - IL_0018: stloc.3 - IL_0019: ldloc.3 + IL_0018: stloc.2 + IL_0019: ldloc.2 IL_001a: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::FailurePattern(class [mscorlib]System.Exception) - IL_001f: stloc.s V_4 - IL_0021: ldloc.s V_4 - IL_0023: brfalse.s IL_0057 - - IL_0025: ldloc.s V_4 - IL_0027: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_002c: stloc.s msg - IL_002e: ldloc.s msg - IL_0030: ldstr "hello" - IL_0035: call bool [netstandard]System.String::Equals(string, + IL_001f: stloc.3 + IL_0020: ldloc.3 + IL_0021: brfalse.s IL_0053 + + IL_0023: ldloc.3 + IL_0024: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() + IL_0029: stloc.s msg + IL_002b: ldloc.s msg + IL_002d: ldstr "hello" + IL_0032: call bool [netstandard]System.String::Equals(string, string) - IL_003a: brfalse.s IL_0057 + IL_0037: brfalse.s IL_0053 - IL_003c: ldloc.s V_4 - IL_003e: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_0043: stloc.s V_6 + IL_0039: ldloc.3 + IL_003a: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() + IL_003f: stloc.s V_5 .line 14,14 : 8,23 '' - IL_0045: ldstr "World" - IL_004a: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) - IL_004f: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0054: stloc.0 - IL_0055: leave.s IL_0062 + IL_0041: ldstr "World" + IL_0046: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) + IL_004b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0050: pop + IL_0051: leave.s IL_005e .line 100001,100001 : 0,0 '' - IL_0057: rethrow - IL_0059: ldnull - IL_005a: unbox.any [FSharp.Core]Microsoft.FSharp.Core.Unit - IL_005f: stloc.0 - IL_0060: leave.s IL_0062 + IL_0053: rethrow + IL_0055: ldnull + IL_0056: unbox.any [FSharp.Core]Microsoft.FSharp.Core.Unit + IL_005b: pop + IL_005c: leave.s IL_005e .line 100001,100001 : 0,0 '' } // end handler - IL_0062: ldloc.0 - IL_0063: pop - IL_0064: ret + IL_005e: ret } // end of method TestFunction3c::TestFunction3c } // end of class TestFunction3c diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction22h.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction22h.il.bsl index 192a1d04752..467c0972190 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction22h.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction22h.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000160 Length: 0x00000056 } .module Testfunction22h.exe -// MVID: {60B68B97-0266-39F6-A745-0383978BB660} +// MVID: {60BD4158-0266-39F6-A745-03835841BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00C90000 +// Image base: 0x07240000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,36 +63,29 @@ .method public static void main@() cil managed { .entrypoint - // Code size 27 (0x1b) + // Code size 21 (0x15) .maxstack 3 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_0, - [1] class [mscorlib]System.Exception V_1) + .locals init ([0] class [mscorlib]System.Exception V_0) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' .line 4,4 : 4,30 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\TestFunctions\\Testfunction22h.fs' .try { IL_0000: call void [mscorlib]System.Console::WriteLine() - IL_0005: ldnull - IL_0006: stloc.0 - IL_0007: leave.s IL_0018 + IL_0005: leave.s IL_0014 .line 5,5 : 1,5 '' } // end .try catch [mscorlib]System.Object { - IL_0009: castclass [mscorlib]System.Exception - IL_000e: stloc.1 + IL_0007: castclass [mscorlib]System.Exception + IL_000c: stloc.0 .line 6,6 : 11,37 '' - IL_000f: call void [mscorlib]System.Console::WriteLine() - IL_0014: ldnull - IL_0015: stloc.0 - IL_0016: leave.s IL_0018 + IL_000d: call void [mscorlib]System.Console::WriteLine() + IL_0012: leave.s IL_0014 .line 100001,100001 : 0,0 '' } // end handler - IL_0018: ldloc.0 - IL_0019: pop - IL_001a: ret + IL_0014: ret } // end of method $Testfunction22h::main@ } // end of class ''.$Testfunction22h diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction3.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction3.il.bsl index 31cb50e6a6b..fe0c97e48f3 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction3.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction3.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000200 Length: 0x00000088 } .module TestFunction3.exe -// MVID: {60B68B97-663A-8929-A745-0383978BB660} +// MVID: {60BD4158-663A-8929-A745-03835841BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06F20000 +// Image base: 0x050D0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -75,21 +75,20 @@ .method public static void TestFunction3() cil managed { - // Code size 51 (0x33) + // Code size 49 (0x31) .maxstack 3 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_0, - [1] int32 x, - [2] class [mscorlib]System.Exception V_2) + .locals init ([0] int32 x, + [1] class [mscorlib]System.Exception V_1) .line 11,11 : 8,31 '' .try { IL_0000: call int32 TestFunction3::TestFunction1() - IL_0005: stloc.1 + IL_0005: stloc.0 .line 12,12 : 8,23 '' IL_0006: ldstr "Hello" IL_000b: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) IL_0010: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0015: stloc.0 + IL_0015: pop IL_0016: leave.s IL_0030 .line 13,13 : 5,9 '' @@ -97,19 +96,17 @@ catch [mscorlib]System.Object { IL_0018: castclass [mscorlib]System.Exception - IL_001d: stloc.2 + IL_001d: stloc.1 .line 14,14 : 8,23 '' IL_001e: ldstr "World" IL_0023: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) IL_0028: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_002d: stloc.0 + IL_002d: pop IL_002e: leave.s IL_0030 .line 100001,100001 : 0,0 '' } // end handler - IL_0030: ldloc.0 - IL_0031: pop - IL_0032: ret + IL_0030: ret } // end of method TestFunction3::TestFunction3 } // end of class TestFunction3 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction4.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction4.il.bsl index 9089ec85b99..799c175fb43 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction4.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/TestFunctions/Testfunction4.il.bsl @@ -36,13 +36,13 @@ // Offset: 0x00000200 Length: 0x00000088 } .module TestFunction4.exe -// MVID: {60B68B97-665B-8929-A745-0383978BB660} +// MVID: {60BD4158-665B-8929-A745-03835841BD60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00F10000 +// Image base: 0x04B90000 // =============== CLASS MEMBERS DECLARATION =================== @@ -75,20 +75,19 @@ .method public static void TestFunction4() cil managed { - // Code size 45 (0x2d) + // Code size 43 (0x2b) .maxstack 3 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_0, - [1] int32 x) + .locals init ([0] int32 x) .line 11,11 : 8,31 '' .try { IL_0000: call int32 TestFunction4::TestFunction1() - IL_0005: stloc.1 + IL_0005: stloc.0 .line 12,12 : 8,23 '' IL_0006: ldstr "Hello" IL_000b: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) IL_0010: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0015: stloc.0 + IL_0015: pop IL_0016: leave.s IL_002a .line 13,13 : 5,12 '' @@ -104,9 +103,7 @@ IL_0029: endfinally .line 100001,100001 : 0,0 '' } // end handler - IL_002a: ldloc.0 - IL_002b: pop - IL_002c: ret + IL_002a: ret } // end of method TestFunction4::TestFunction4 } // end of class TestFunction4 diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/Tuples/TupleElimination.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/Tuples/TupleElimination.il.bsl index ba2f7ee8e8e..32383a15efa 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/Tuples/TupleElimination.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/Tuples/TupleElimination.il.bsl @@ -41,13 +41,13 @@ // Offset: 0x00000230 Length: 0x0000007B } .module TupleElimination.exe -// MVID: {60D46F2D-DFDD-92DF-A745-03832D6FD460} +// MVID: {60EF4161-DFDD-92DF-A745-03836141EF60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06A70000 +// Image base: 0x065E0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -56,39 +56,26 @@ extends [mscorlib]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .method assembly static void p@5(!!a v) cil managed - { - // Code size 30 (0x1e) - .maxstack 4 - .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> V_0) - .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 15,27 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\Tuples\\TupleElimination.fs' - IL_0000: ldstr "%A" - IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,!!a>::.ctor(string) - IL_000a: stloc.0 - IL_000b: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() - IL_0010: ldloc.0 - IL_0011: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter>(class [mscorlib]System.IO.TextWriter, - class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_0016: ldarg.0 - IL_0017: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_001c: pop - IL_001d: ret - } // end of method TupleElimination::p@5 - .method public static int32 main(string[] argv) cil managed { .entrypoint .custom instance void [FSharp.Core]Microsoft.FSharp.Core.EntryPointAttribute::.ctor() = ( 01 00 00 00 ) - // Code size 79 (0x4f) + // Code size 205 (0xcd) .maxstack 5 .locals init ([0] class [mscorlib]System.Collections.Generic.Dictionary`2 dic, [1] int32 i, [2] bool b, - [3] int64 l, - [4] bool V_4, - [5] class [mscorlib]System.Tuple`2 t) - .line 7,7 : 5,64 '' + [3] class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> V_3, + [4] int32 V_4, + [5] class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> V_5, + [6] int64 l, + [7] bool V_7, + [8] class [mscorlib]System.Tuple`2 t, + [9] int64 V_9, + [10] class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> V_10, + [11] class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4,class [FSharp.Core]Microsoft.FSharp.Core.Unit>,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> V_11) + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 7,7 : 5,64 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\CodeGen\\EmittedIL\\Tuples\\TupleElimination.fs' IL_0000: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2::.ctor() IL_0005: stloc.0 .line 9,9 : 31,48 '' @@ -99,40 +86,79 @@ !1&) IL_000f: stloc.2 .line 10,10 : 5,8 '' - IL_0010: ldloc.2 - IL_0011: call void TupleElimination::p@5(!!0) - IL_0016: nop + IL_0010: ldstr "%A" + IL_0015: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,bool>::.ctor(string) + IL_001a: stloc.3 + IL_001b: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0020: ldloc.3 + IL_0021: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter>(class [mscorlib]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0026: ldloc.2 + IL_0027: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_002c: pop .line 11,11 : 5,8 '' - IL_0017: ldloc.1 - IL_0018: call void TupleElimination::p@5(!!0) - IL_001d: nop + IL_002d: ldloc.1 + IL_002e: stloc.s V_4 + IL_0030: ldstr "%A" + IL_0035: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::.ctor(string) + IL_003a: stloc.s V_5 + IL_003c: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0041: ldloc.s V_5 + IL_0043: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter>(class [mscorlib]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0048: ldloc.s V_4 + IL_004a: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_004f: pop .line 14,14 : 38,65 '' - IL_001e: ldstr "123" - IL_0023: ldloca.s l - IL_0025: call bool [mscorlib]System.Int64::TryParse(string, + IL_0050: ldstr "123" + IL_0055: ldloca.s l + IL_0057: call bool [mscorlib]System.Int64::TryParse(string, int64&) - IL_002a: stloc.s V_4 + IL_005c: stloc.s V_7 .line 14,14 : 5,65 '' - IL_002c: ldloc.s V_4 - IL_002e: ldloc.3 - IL_002f: newobj instance void class [mscorlib]System.Tuple`2::.ctor(!0, + IL_005e: ldloc.s V_7 + IL_0060: ldloc.s l + IL_0062: newobj instance void class [mscorlib]System.Tuple`2::.ctor(!0, !1) - IL_0034: stloc.s t + IL_0067: stloc.s t .line 15,15 : 5,8 '' - IL_0036: ldloc.s V_4 - IL_0038: call void TupleElimination::p@5(!!0) - IL_003d: nop + IL_0069: ldstr "%A" + IL_006e: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,bool>::.ctor(string) + IL_0073: stloc.3 + IL_0074: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_0079: ldloc.3 + IL_007a: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter>(class [mscorlib]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_007f: ldloc.s V_7 + IL_0081: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0086: pop .line 16,16 : 5,8 '' - IL_003e: ldloc.3 - IL_003f: call void TupleElimination::p@5(!!0) - IL_0044: nop + IL_0087: ldloc.s l + IL_0089: stloc.s V_9 + IL_008b: ldstr "%A" + IL_0090: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,int64>::.ctor(string) + IL_0095: stloc.s V_10 + IL_0097: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_009c: ldloc.s V_10 + IL_009e: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter>(class [mscorlib]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00a3: ldloc.s V_9 + IL_00a5: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_00aa: pop .line 21,21 : 5,9 '' - IL_0045: ldloc.s t - IL_0047: call void TupleElimination::p@5>(!!0) - IL_004c: nop + IL_00ab: ldstr "%A" + IL_00b0: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5,class [FSharp.Core]Microsoft.FSharp.Core.Unit>,class [mscorlib]System.IO.TextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [mscorlib]System.Tuple`2>::.ctor(string) + IL_00b5: stloc.s V_11 + IL_00b7: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out() + IL_00bc: ldloc.s V_11 + IL_00be: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>(class [mscorlib]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_00c3: ldloc.s t + IL_00c5: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0) + IL_00ca: pop .line 23,23 : 5,6 '' - IL_004d: ldc.i4.0 - IL_004e: ret + IL_00cb: ldc.i4.0 + IL_00cc: ret } // end of method TupleElimination::main } // end of class TupleElimination diff --git a/tests/fsharpqa/Source/KnownFail.txt b/tests/fsharpqa/Source/KnownFail.txt index 20e99f4337b..51e03a36340 100644 --- a/tests/fsharpqa/Source/KnownFail.txt +++ b/tests/fsharpqa/Source/KnownFail.txt @@ -89,4 +89,4 @@ CHK Stress (2766.fs) -- failed !NETFX35 FSharp.Core.UnitTests.Collections.SeqModule2.SystemLinqSelectWithException -- failed !NETFX35 FSharp.Core.UnitTests.Collections.SeqModule2.SystemLinqSelectWithSideEffects -- failed !CURRENTUICULTURE1033 FSharp.Core.UnitTests.Control.AsyncModule.ContinuationsThreadingDetails.AsyncSansSyncContext -- failed -!CURRENTUICULTURE1033 FSharp.Core.UnitTests.Control.AsyncModule.ContinuationsThreadingDetails.AsyncWithSyncContext -- failed \ No newline at end of file +!CURRENTUICULTURE1033 FSharp.Core.UnitTests.Control.AsyncModule.ContinuationsThreadingDetails.AsyncWithSyncContext -- failed diff --git a/tests/fsharpqa/Source/Optimizations/CompareIL.cmd b/tests/fsharpqa/Source/Optimizations/CompareIL.cmd index ca278788982..b8d70002021 100644 --- a/tests/fsharpqa/Source/Optimizations/CompareIL.cmd +++ b/tests/fsharpqa/Source/Optimizations/CompareIL.cmd @@ -3,8 +3,8 @@ REM == %1 --> assembly ildasm /TEXT /LINENUM /NOBAR "%~nx1" >"%~n1.il" IF %ERRORLEVEL% NEQ 0 exit /b 1 -echo ..\..\..\testenv\bin\ILComparer.exe "%~n1.il.bsl" "%~n1.il" -..\..\..\testenv\bin\ILComparer.exe "%~n1.il.bsl" "%~n1.il" +echo %~dp0..\..\testenv\bin\ILComparer.exe "%~n1.il.bsl" "%~n1.il" + %~dp0..\..\testenv\bin\ILComparer.exe "%~n1.il.bsl" "%~n1.il" IF %ERRORLEVEL% EQU 0 exit /b 0 diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnArray01.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnArray01.il.bsl index 38b3a3aa80c..46d1b653558 100644 --- a/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnArray01.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnArray01.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly ForEachOnArray01 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.ForEachOnArray01 { - // Offset: 0x00000000 Length: 0x000001E0 + // Offset: 0x00000000 Length: 0x000001DC } .mresource public FSharpOptimizationData.ForEachOnArray01 { - // Offset: 0x000001E8 Length: 0x0000007C + // Offset: 0x000001E0 Length: 0x0000007C } .module ForEachOnArray01.dll -// MVID: {59B18AEE-7E2E-D3AE-A745-0383EE8AB159} +// MVID: {60BE1F17-7E2E-D3AE-A745-0383171FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00D00000 +// Image base: 0x06F50000 // =============== CLASS MEMBERS DECLARATION =================== @@ -59,7 +59,7 @@ [1] int32 V_1, [2] int32 x) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 6,6 : 6,23 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\ForLoop\\ForEachOnArray01.fs' + .line 6,6 : 6,23 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\ForLoop\\ForEachOnArray01.fs' IL_0000: ldc.i4.0 IL_0001: stloc.0 .line 7,7 : 6,21 '' diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnList01.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnList01.il.bsl index efb793fbe5f..3621bd1889e 100644 --- a/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnList01.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnList01.il.bsl @@ -41,13 +41,13 @@ // Offset: 0x000002F0 Length: 0x000000DB } .module ForEachOnList01.dll -// MVID: {5FCFFFA6-56DF-F74F-A745-0383A6FFCF5F} +// MVID: {60BE1F17-56DF-F74F-A745-0383171FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x072F0000 +// Image base: 0x06EA0000 // =============== CLASS MEMBERS DECLARATION =================== diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnString01.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnString01.il.bsl index b62060e69f4..0724c4fc823 100644 --- a/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnString01.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnString01.il.bsl @@ -41,13 +41,13 @@ // Offset: 0x00000358 Length: 0x000000FF } .module ForEachOnString01.dll -// MVID: {5FCFFFA6-105C-852B-A745-0383A6FFCF5F} +// MVID: {60BE1F17-105C-852B-A745-0383171FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06C70000 +// Image base: 0x057C0000 // =============== CLASS MEMBERS DECLARATION =================== diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/NoAllocationOfTuple01.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/NoAllocationOfTuple01.il.bsl index 4dd6df631f0..86b17c9f28d 100644 --- a/tests/fsharpqa/Source/Optimizations/ForLoop/NoAllocationOfTuple01.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/NoAllocationOfTuple01.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly NoAllocationOfTuple01 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.NoAllocationOfTuple01 { - // Offset: 0x00000000 Length: 0x000001E0 + // Offset: 0x00000000 Length: 0x000001DC } .mresource public FSharpOptimizationData.NoAllocationOfTuple01 { - // Offset: 0x000001E8 Length: 0x00000085 + // Offset: 0x000001E0 Length: 0x00000085 } .module NoAllocationOfTuple01.dll -// MVID: {59B18AEE-13B5-F699-A745-0383EE8AB159} +// MVID: {60BE1F17-13B5-F699-A745-0383171FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x03460000 +// Image base: 0x08DC0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -60,7 +60,7 @@ [2] int32 V_2, [3] int32 j) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 6,6 : 5,31 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\ForLoop\\NoAllocationOfTuple01.fs' + .line 6,6 : 5,31 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\ForLoop\\NoAllocationOfTuple01.fs' IL_0000: ldarg.0 IL_0001: call !!0[] [FSharp.Core]Microsoft.FSharp.Collections.ArrayModule::ZeroCreate(int32) IL_0006: stloc.0 diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable01.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable01.il.bsl index a56c18506ea..f3218f9ca6a 100644 --- a/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable01.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable01.il.bsl @@ -34,20 +34,20 @@ } .mresource public FSharpSignatureData.NoIEnumerable01 { - // Offset: 0x00000000 Length: 0x000001CB + // Offset: 0x00000000 Length: 0x000001CD } .mresource public FSharpOptimizationData.NoIEnumerable01 { - // Offset: 0x000001D0 Length: 0x0000006C + // Offset: 0x000001D8 Length: 0x0000006C } .module NoIEnumerable01.dll -// MVID: {5F1FBE49-31A1-8DCB-A745-038349BE1F5F} +// MVID: {60BE1F17-31A1-8DCB-A745-0383171FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x07010000 +// Image base: 0x06B80000 // =============== CLASS MEMBERS DECLARATION =================== @@ -64,7 +64,7 @@ [1] int32 i, [2] class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_2) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 7,7 : 4,22 'C:\\kevinransom\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\ForLoop\\NoIEnumerable01.fsx' + .line 7,7 : 4,22 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\ForLoop\\NoIEnumerable01.fsx' IL_0000: ldc.i4.1 IL_0001: stloc.1 IL_0002: ldarg.0 diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable02.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable02.il.bsl index 80a2f8d02da..1076cf2598b 100644 --- a/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable02.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable02.il.bsl @@ -34,20 +34,20 @@ } .mresource public FSharpSignatureData.NoIEnumerable02 { - // Offset: 0x00000000 Length: 0x000001CB + // Offset: 0x00000000 Length: 0x000001CD } .mresource public FSharpOptimizationData.NoIEnumerable02 { - // Offset: 0x000001D0 Length: 0x0000006C + // Offset: 0x000001D8 Length: 0x0000006C } .module NoIEnumerable02.dll -// MVID: {5F1FBE49-5066-4012-A745-038349BE1F5F} +// MVID: {60BE1F17-5066-4012-A745-0383171FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x07280000 +// Image base: 0x05170000 // =============== CLASS MEMBERS DECLARATION =================== @@ -64,7 +64,7 @@ [1] int32 i, [2] class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_2) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 7,7 : 4,24 'C:\\kevinransom\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\ForLoop\\NoIEnumerable02.fsx' + .line 7,7 : 4,24 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\ForLoop\\NoIEnumerable02.fsx' IL_0000: ldc.i4.s 100 IL_0002: stloc.1 IL_0003: ldarg.0 diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable03.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable03.il.bsl index 7e4eeb1fcb7..dc81a5ebb66 100644 --- a/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable03.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable03.il.bsl @@ -34,20 +34,20 @@ } .mresource public FSharpSignatureData.NoIEnumerable03 { - // Offset: 0x00000000 Length: 0x000001D9 + // Offset: 0x00000000 Length: 0x000001DB } .mresource public FSharpOptimizationData.NoIEnumerable03 { // Offset: 0x000001E0 Length: 0x0000006C } .module NoIEnumerable03.dll -// MVID: {5F1FBE49-7903-6020-A745-038349BE1F5F} +// MVID: {60BE1F17-7903-6020-A745-0383171FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x070D0000 +// Image base: 0x069A0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -66,7 +66,7 @@ [1] int32 i, [2] class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4 V_2) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 7,7 : 4,22 'C:\\kevinransom\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\ForLoop\\NoIEnumerable03.fsx' + .line 7,7 : 4,22 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\ForLoop\\NoIEnumerable03.fsx' IL_0000: ldarg.0 IL_0001: stloc.1 IL_0002: ldarg.1 diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/ZeroToArrLength01.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/ZeroToArrLength01.il.bsl index a27da5651f5..c8029558865 100644 --- a/tests/fsharpqa/Source/Optimizations/ForLoop/ZeroToArrLength01.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/ZeroToArrLength01.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly ZeroToArrLength01 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.ZeroToArrLength01 { - // Offset: 0x00000000 Length: 0x000001E0 + // Offset: 0x00000000 Length: 0x000001DC } .mresource public FSharpOptimizationData.ZeroToArrLength01 { - // Offset: 0x000001E8 Length: 0x0000007B + // Offset: 0x000001E0 Length: 0x0000007B } .module ZeroToArrLength01.dll -// MVID: {59B18AEE-A3D0-03A7-A745-0383EE8AB159} +// MVID: {60BE1F17-A3D0-03A7-A745-0383171FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x02E70000 +// Image base: 0x06B20000 // =============== CLASS MEMBERS DECLARATION =================== @@ -57,7 +57,7 @@ .maxstack 5 .locals init ([0] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 6,6 : 5,35 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\ForLoop\\ZeroToArrLength01.fs' + .line 6,6 : 5,35 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\ForLoop\\ZeroToArrLength01.fs' IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: br.s IL_0010 diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/ZeroToArrLength02.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/ZeroToArrLength02.il.bsl index 253d6843729..2d3d3f44e26 100644 --- a/tests/fsharpqa/Source/Optimizations/ForLoop/ZeroToArrLength02.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/ZeroToArrLength02.il.bsl @@ -1,6 +1,9 @@ // Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. + + + // Metadata version: v4.0.30319 .assembly extern mscorlib { @@ -17,28 +20,33 @@ .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, int32, int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + // --- The following custom attribute is added automatically, do not uncomment ------- // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 01 00 00 00 00 00 ) + .hash algorithm 0x00008004 .ver 0:0:0:0 } .mresource public FSharpSignatureData.ZeroToArrLength02 { - // Offset: 0x00000000 Length: 0x0000020E + // Offset: 0x00000000 Length: 0x000001DC } .mresource public FSharpOptimizationData.ZeroToArrLength02 { - // Offset: 0x00000218 Length: 0x0000007B + // Offset: 0x000001E0 Length: 0x0000007B } .module ZeroToArrLength02.dll -// MVID: {5F9557F9-A36B-03A7-A745-0383F957955F} +// MVID: {60BE1F17-A36B-03A7-A745-0383171FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x04D90000 +// Image base: 0x05860000 + + // =============== CLASS MEMBERS DECLARATION =================== + .class public abstract auto ansi sealed ZeroToArrLength02 extends [mscorlib]System.Object { @@ -50,7 +58,7 @@ .locals init ([0] int32 V_0, [1] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 6,6 : 5,41 'C:\\Users\\Michelle\\Desktop\\Personal\\Repos\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\ForLoop\\ZeroToArrLength02.fs' + .line 6,6 : 5,41 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\ForLoop\\ZeroToArrLength02.fs' IL_0000: ldc.i4.0 IL_0001: stloc.1 IL_0002: ldarg.0 @@ -61,6 +69,7 @@ IL_000b: ldloc.0 IL_000c: ldloc.1 IL_000d: blt.s IL_0021 + .line 7,7 : 9,21 '' IL_000f: ldarg.0 IL_0010: ldloc.1 @@ -76,12 +85,18 @@ IL_001d: ldc.i4.1 IL_001e: add IL_001f: bne.un.s IL_000f + IL_0021: ret } // end of method ZeroToArrLength02::f1 + } // end of class ZeroToArrLength02 + .class private abstract auto ansi sealed ''.$ZeroToArrLength02 extends [mscorlib]System.Object { } // end of class ''.$ZeroToArrLength02 + + // ============================================================= + // *********** DISASSEMBLY COMPLETE *********************** diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare01.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare01.il.bsl index 974905405eb..74527f0d702 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare01.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare01.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Compare01 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Compare01 { - // Offset: 0x00000000 Length: 0x00000225 + // Offset: 0x00000000 Length: 0x00000221 } .mresource public FSharpOptimizationData.Compare01 { - // Offset: 0x00000230 Length: 0x000000B2 + // Offset: 0x00000228 Length: 0x000000B2 } .module Compare01.dll -// MVID: {59B18AEE-04A0-F88E-A745-0383EE8AB159} +// MVID: {60BE1F16-04A0-F88E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00FF0000 +// Image base: 0x05230000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,7 +63,7 @@ [1] int32 i, [2] int32 V_2) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Compare01.fsx' + .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare01.fsx' IL_0000: ldc.i4.1 IL_0001: stloc.0 .line 9,9 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare02.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare02.il.bsl index 74bd16af665..035762e696b 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare02.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare02.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Compare02 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Compare02 { - // Offset: 0x00000000 Length: 0x0000022C + // Offset: 0x00000000 Length: 0x00000228 } .mresource public FSharpOptimizationData.Compare02 { // Offset: 0x00000230 Length: 0x000000B9 } .module Compare02.dll -// MVID: {59B18AEE-0481-F88E-A745-0383EE8AB159} +// MVID: {60BE1F16-0481-F88E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00BA0000 +// Image base: 0x07180000 // =============== CLASS MEMBERS DECLARATION =================== @@ -64,7 +64,7 @@ [2] int32 V_2, [3] int32 V_3) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Compare02.fsx' + .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare02.fsx' IL_0000: ldc.i4.1 IL_0001: stloc.0 .line 8,8 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare03.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare03.il.bsl index 6bc3566d45e..f4542c78376 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare03.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare03.il.bsl @@ -34,20 +34,20 @@ } .mresource public FSharpSignatureData.Compare03 { - // Offset: 0x00000000 Length: 0x00000231 + // Offset: 0x00000000 Length: 0x00000233 } .mresource public FSharpOptimizationData.Compare03 { // Offset: 0x00000238 Length: 0x000000B9 } .module Compare03.dll -// MVID: {5F1FBE49-0562-F88E-A745-038349BE1F5F} +// MVID: {60BE1F16-0562-F88E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06C20000 +// Image base: 0x09540000 // =============== CLASS MEMBERS DECLARATION =================== @@ -70,7 +70,7 @@ [3] int32 V_3, [4] int32 V_4) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,25 'C:\\kevinransom\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare03.fsx' + .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare03.fsx' IL_0000: ldc.i4.1 IL_0001: stloc.0 .line 8,8 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare04.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare04.il.bsl index a48aceacf7b..3c703ad0464 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare04.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare04.il.bsl @@ -34,20 +34,20 @@ } .mresource public FSharpSignatureData.Compare04 { - // Offset: 0x00000000 Length: 0x00000231 + // Offset: 0x00000000 Length: 0x00000233 } .mresource public FSharpOptimizationData.Compare04 { // Offset: 0x00000238 Length: 0x000000B9 } .module Compare04.dll -// MVID: {5F1FBE49-053B-F88E-A745-038349BE1F5F} +// MVID: {60BE1F16-053B-F88E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06750000 +// Image base: 0x04FB0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -71,7 +71,7 @@ [4] int32 V_4, [5] int32 V_5) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,25 'C:\\kevinransom\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare04.fsx' + .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare04.fsx' IL_0000: ldc.i4.1 IL_0001: stloc.0 .line 8,8 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare05.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare05.il.bsl index 1b66e37d298..5bf6d5ccbd1 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare05.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare05.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Compare05 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Compare05 { - // Offset: 0x00000000 Length: 0x000006EC + // Offset: 0x00000000 Length: 0x000006DC } .mresource public FSharpOptimizationData.Compare05 { - // Offset: 0x000006F0 Length: 0x000003BA + // Offset: 0x000006E0 Length: 0x000003BA } .module Compare05.dll -// MVID: {59B18AEE-051C-F88E-A745-0383EE8AB159} +// MVID: {60BE1F16-051C-F88E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x002D0000 +// Image base: 0x06AE0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -187,7 +187,7 @@ [4] int32 V_4, [5] int32 V_5) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Compare05.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare05.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare06.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare06.il.bsl index 49c709033de..f79e000a95f 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare06.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare06.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Compare06 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Compare06 { - // Offset: 0x00000000 Length: 0x000006DF + // Offset: 0x00000000 Length: 0x000006CF } .mresource public FSharpOptimizationData.Compare06 { - // Offset: 0x000006E8 Length: 0x000003BC + // Offset: 0x000006D8 Length: 0x000003BC } .module Compare06.dll -// MVID: {59B18AEE-04FD-F88E-A745-0383EE8AB159} +// MVID: {60BE1F16-04FD-F88E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x02E80000 +// Image base: 0x06A50000 // =============== CLASS MEMBERS DECLARATION =================== @@ -130,7 +130,7 @@ [2] int32 V_2, [3] int32 V_3) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Compare06.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare06.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.bsl index 70335b05d20..9effce1baff 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare07.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Compare07 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Compare07 { - // Offset: 0x00000000 Length: 0x0000089A + // Offset: 0x00000000 Length: 0x0000088A } .mresource public FSharpOptimizationData.Compare07 { - // Offset: 0x000008A0 Length: 0x00000692 + // Offset: 0x00000890 Length: 0x0000068C } .module Compare07.dll -// MVID: {59B18AEE-05DE-F88E-A745-0383EE8AB159} +// MVID: {60BE1F16-05DE-F88E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x02BA0000 +// Image base: 0x05810000 // =============== CLASS MEMBERS DECLARATION =================== @@ -187,7 +187,7 @@ [4] !a V_4, [5] !a V_5) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Compare07.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare07.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare08.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare08.il.bsl index 29f55a0cb58..008f1eb52b1 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare08.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare08.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Compare08 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Compare08 { - // Offset: 0x00000000 Length: 0x00000230 + // Offset: 0x00000000 Length: 0x0000022C } .mresource public FSharpOptimizationData.Compare08 { - // Offset: 0x00000238 Length: 0x000000B2 + // Offset: 0x00000230 Length: 0x000000B2 } .module Compare08.dll -// MVID: {59B18AEE-03E7-F88E-A745-0383EE8AB159} +// MVID: {60BE1F16-03E7-F88E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01590000 +// Image base: 0x06D10000 // =============== CLASS MEMBERS DECLARATION =================== @@ -64,7 +64,7 @@ [2] uint8[] t2, [3] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Compare08.fsx' + .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare08.fsx' IL_0000: ldc.i4.1 IL_0001: stloc.0 .line 6,6 : 8,35 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare09.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare09.il.bsl index 4d890783eed..f8a93849b92 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare09.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare09.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Compare09 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Compare09 { - // Offset: 0x00000000 Length: 0x00000230 + // Offset: 0x00000000 Length: 0x0000022C } .mresource public FSharpOptimizationData.Compare09 { - // Offset: 0x00000238 Length: 0x000000B2 + // Offset: 0x00000230 Length: 0x000000B2 } .module Compare09.dll -// MVID: {59B18AEE-03C8-F88E-A745-0383EE8AB159} +// MVID: {60BE1F16-03C8-F88E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01020000 +// Image base: 0x06710000 // =============== CLASS MEMBERS DECLARATION =================== @@ -64,7 +64,7 @@ [2] int32[] t2, [3] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Compare09.fsx' + .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare09.fsx' IL_0000: ldc.i4.1 IL_0001: stloc.0 .line 6,6 : 8,31 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.bsl index 16bada503c5..5b5491417d9 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare10.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Compare10 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Compare10 { - // Offset: 0x00000000 Length: 0x00000AA4 + // Offset: 0x00000000 Length: 0x00000A94 } .mresource public FSharpOptimizationData.Compare10 { - // Offset: 0x00000AA8 Length: 0x0000058E + // Offset: 0x00000A98 Length: 0x0000058E } .module Compare10.dll -// MVID: {59B18AEE-04BF-1753-A745-0383EE8AB159} +// MVID: {60BE1F16-04BF-1753-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x002E0000 +// Image base: 0x06C00000 // =============== CLASS MEMBERS DECLARATION =================== @@ -187,7 +187,7 @@ [4] int32 V_4, [5] int32 V_5) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Compare10.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare10.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare11.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare11.il.bsl index 7f37b719bb4..4293dce0c19 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare11.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Compare11.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Compare11 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Compare11 { - // Offset: 0x00000000 Length: 0x00000230 + // Offset: 0x00000000 Length: 0x0000022C } .mresource public FSharpOptimizationData.Compare11 { - // Offset: 0x00000238 Length: 0x000000B1 + // Offset: 0x00000230 Length: 0x000000B1 } .module Compare11.dll -// MVID: {59B18AEE-04A0-1753-A745-0383EE8AB159} +// MVID: {60BE1F16-04A0-1753-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x010A0000 +// Image base: 0x068D0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -62,7 +62,7 @@ .locals init ([0] bool x, [1] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,29 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Compare11.fsx' + .line 5,5 : 8,29 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Compare11.fsx' IL_0000: ldc.i4.0 IL_0001: stloc.0 .line 9,9 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals01.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals01.il.bsl index c722fc2d31f..6cd820bc0f7 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals01.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals01.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Equals01 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Equals01 { - // Offset: 0x00000000 Length: 0x00000234 + // Offset: 0x00000000 Length: 0x00000230 } .mresource public FSharpOptimizationData.Equals01 { // Offset: 0x00000238 Length: 0x000000B6 } .module Equals01.dll -// MVID: {59B18AEE-0759-50B1-A745-0383EE8AB159} +// MVID: {60BE1F16-0759-50B1-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x02D70000 +// Image base: 0x06A90000 // =============== CLASS MEMBERS DECLARATION =================== @@ -62,7 +62,7 @@ .locals init ([0] bool x, [1] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,29 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Equals01.fsx' + .line 5,5 : 8,29 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Equals01.fsx' IL_0000: ldc.i4.0 IL_0001: stloc.0 .line 8,8 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals02.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals02.il.bsl index 93aa98ffb94..10efc022f68 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals02.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals02.il.bsl @@ -34,20 +34,20 @@ } .mresource public FSharpSignatureData.Equals02 { - // Offset: 0x00000000 Length: 0x0000022E + // Offset: 0x00000000 Length: 0x00000230 } .mresource public FSharpOptimizationData.Equals02 { // Offset: 0x00000238 Length: 0x000000B6 } .module Equals02.dll -// MVID: {5F1FBE49-0759-B6D8-A745-038349BE1F5F} +// MVID: {60BE1F16-0759-B6D8-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x054B0000 +// Image base: 0x05340000 // =============== CLASS MEMBERS DECLARATION =================== @@ -67,7 +67,7 @@ .locals init ([0] bool x, [1] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,29 'C:\\kevinransom\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Equals02.fsx' + .line 5,5 : 8,29 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Equals02.fsx' IL_0000: ldc.i4.0 IL_0001: stloc.0 .line 8,8 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals03.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals03.il.bsl index 84da5e6eb5d..9942460e50b 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals03.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals03.il.bsl @@ -34,20 +34,20 @@ } .mresource public FSharpSignatureData.Equals03 { - // Offset: 0x00000000 Length: 0x0000022E + // Offset: 0x00000000 Length: 0x00000230 } .mresource public FSharpOptimizationData.Equals03 { // Offset: 0x00000238 Length: 0x000000B6 } .module Equals03.dll -// MVID: {5F1FBE49-0759-3313-A745-038349BE1F5F} +// MVID: {60BE1F16-0759-3313-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x071F0000 +// Image base: 0x05410000 // =============== CLASS MEMBERS DECLARATION =================== @@ -67,7 +67,7 @@ .locals init ([0] bool x, [1] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,29 'C:\\kevinransom\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Equals03.fsx' + .line 5,5 : 8,29 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Equals03.fsx' IL_0000: ldc.i4.0 IL_0001: stloc.0 .line 8,8 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals04.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals04.il.bsl index 6ad198b4879..f250eab6384 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals04.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals04.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Equals04 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Equals04 { - // Offset: 0x00000000 Length: 0x000006E8 + // Offset: 0x00000000 Length: 0x000006D8 } .mresource public FSharpOptimizationData.Equals04 { - // Offset: 0x000006F0 Length: 0x000003B7 + // Offset: 0x000006E0 Length: 0x000003B7 } .module Equals04.dll -// MVID: {59B18AEE-0759-EA8A-A745-0383EE8AB159} +// MVID: {60BE1F16-0759-EA8A-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x002D0000 +// Image base: 0x07050000 // =============== CLASS MEMBERS DECLARATION =================== @@ -187,7 +187,7 @@ [4] int32 V_4, [5] int32 V_5) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Equals04.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Equals04.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals05.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals05.il.bsl index ecc013d450a..0c1255075bf 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals05.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals05.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Equals05 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Equals05 { - // Offset: 0x00000000 Length: 0x000006DB + // Offset: 0x00000000 Length: 0x000006CB } .mresource public FSharpOptimizationData.Equals05 { - // Offset: 0x000006E0 Length: 0x000003B9 + // Offset: 0x000006D0 Length: 0x000003B9 } .module Equals05.dll -// MVID: {59B18AEE-0759-CBC5-A745-0383EE8AB159} +// MVID: {60BE1F16-0759-CBC5-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x033B0000 +// Image base: 0x067E0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -130,7 +130,7 @@ [2] int32 V_2, [3] int32 V_3) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Equals05.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Equals05.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.bsl index 91247bff24d..0a53da50d62 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals06.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Equals06 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Equals06 { - // Offset: 0x00000000 Length: 0x00000896 + // Offset: 0x00000000 Length: 0x00000886 } .mresource public FSharpOptimizationData.Equals06 { - // Offset: 0x000008A0 Length: 0x0000068E + // Offset: 0x00000890 Length: 0x00000688 } .module Equals06.dll -// MVID: {59B18AEE-0759-31EC-A745-0383EE8AB159} +// MVID: {60BE1F16-0759-31EC-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01B90000 +// Image base: 0x06DA0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -187,7 +187,7 @@ [4] !a V_4, [5] !a V_5) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Equals06.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Equals06.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals07.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals07.il.bsl index 91f97c289a2..e652f362b84 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals07.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals07.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Equals07 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Equals07 { - // Offset: 0x00000000 Length: 0x0000022D + // Offset: 0x00000000 Length: 0x00000229 } .mresource public FSharpOptimizationData.Equals07 { - // Offset: 0x00000238 Length: 0x000000AF + // Offset: 0x00000230 Length: 0x000000AF } .module Equals07.dll -// MVID: {59B18AEE-0759-AE27-A745-0383EE8AB159} +// MVID: {60BE1F16-0759-AE27-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01C80000 +// Image base: 0x06B40000 // =============== CLASS MEMBERS DECLARATION =================== @@ -64,7 +64,7 @@ [2] uint8[] t2, [3] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,29 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Equals07.fsx' + .line 5,5 : 8,29 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Equals07.fsx' IL_0000: ldc.i4.0 IL_0001: stloc.0 .line 6,6 : 8,35 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals08.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals08.il.bsl index 55da6ee102e..2a51fe48508 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals08.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals08.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Equals08 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Equals08 { - // Offset: 0x00000000 Length: 0x0000022D + // Offset: 0x00000000 Length: 0x00000229 } .mresource public FSharpOptimizationData.Equals08 { - // Offset: 0x00000238 Length: 0x000000AF + // Offset: 0x00000230 Length: 0x000000AF } .module Equals08.dll -// MVID: {59B18AEE-0759-659E-A745-0383EE8AB159} +// MVID: {60BE1F16-0759-659E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01090000 +// Image base: 0x05730000 // =============== CLASS MEMBERS DECLARATION =================== @@ -64,7 +64,7 @@ [2] int32[] t2, [3] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,29 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Equals08.fsx' + .line 5,5 : 8,29 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Equals08.fsx' IL_0000: ldc.i4.0 IL_0001: stloc.0 .line 6,6 : 8,31 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.bsl index 8985acaa02b..c22e81d41e2 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Equals09.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Equals09 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Equals09 { - // Offset: 0x00000000 Length: 0x00000AA0 + // Offset: 0x00000000 Length: 0x00000A90 } .mresource public FSharpOptimizationData.Equals09 { - // Offset: 0x00000AA8 Length: 0x0000058B + // Offset: 0x00000A98 Length: 0x0000058B } .module Equals09.dll -// MVID: {59B18AEE-0759-46D9-A745-0383EE8AB159} +// MVID: {60BE1F16-0759-46D9-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x02720000 +// Image base: 0x066B0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -187,7 +187,7 @@ [4] int32 V_4, [5] int32 V_5) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Equals09.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Equals09.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash01.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash01.il.bsl index cb63a42741b..5d4ed72b3e4 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash01.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash01.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Hash01 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Hash01 { - // Offset: 0x00000000 Length: 0x00000219 + // Offset: 0x00000000 Length: 0x00000215 } .mresource public FSharpOptimizationData.Hash01 { // Offset: 0x00000220 Length: 0x000000A9 } .module Hash01.dll -// MVID: {59B18AEE-9642-78D3-A745-0383EE8AB159} +// MVID: {60BE1F16-9642-78D3-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x02FB0000 +// Image base: 0x06B70000 // =============== CLASS MEMBERS DECLARATION =================== @@ -62,7 +62,7 @@ .locals init ([0] int32 x, [1] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash01.fsx' + .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash01.fsx' IL_0000: ldc.i4.1 IL_0001: stloc.0 .line 6,6 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash02.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash02.il.bsl index 985bcae6f37..48f1c42fb76 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash02.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash02.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Hash02 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Hash02 { - // Offset: 0x00000000 Length: 0x00000220 + // Offset: 0x00000000 Length: 0x0000021C } .mresource public FSharpOptimizationData.Hash02 { - // Offset: 0x00000228 Length: 0x0000010B + // Offset: 0x00000220 Length: 0x0000010B } .module Hash02.dll -// MVID: {59B18AEE-9642-796E-A745-0383EE8AB159} +// MVID: {60BE1F16-9642-796E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01920000 +// Image base: 0x05400000 // =============== CLASS MEMBERS DECLARATION =================== @@ -60,7 +60,7 @@ // Code size 1 (0x1) .maxstack 8 .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 7,8 : 8,29 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash02.fsx' + .line 7,8 : 8,29 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash02.fsx' IL_0000: ret } // end of method HashMicroPerfAndCodeGenerationTests::f4_triple diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash03.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash03.il.bsl index e9e9c2049d8..08951863dfe 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash03.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash03.il.bsl @@ -34,20 +34,20 @@ } .mresource public FSharpSignatureData.Hash03 { - // Offset: 0x00000000 Length: 0x0000021A + // Offset: 0x00000000 Length: 0x0000021C } .mresource public FSharpOptimizationData.Hash03 { // Offset: 0x00000220 Length: 0x000000B0 } .module Hash03.dll -// MVID: {5F1FBE49-9642-788D-A745-038349BE1F5F} +// MVID: {60BE1F16-9642-788D-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x05560000 +// Image base: 0x06A60000 // =============== CLASS MEMBERS DECLARATION =================== @@ -67,7 +67,7 @@ .locals init ([0] int32 x, [1] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,25 'C:\\kevinransom\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash03.fsx' + .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash03.fsx' IL_0000: ldc.i4.1 IL_0001: stloc.0 .line 7,7 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash04.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash04.il.bsl index 5c6850db0a8..e48efdc6f7a 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash04.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash04.il.bsl @@ -34,20 +34,20 @@ } .mresource public FSharpSignatureData.Hash04 { - // Offset: 0x00000000 Length: 0x0000021A + // Offset: 0x00000000 Length: 0x0000021C } .mresource public FSharpOptimizationData.Hash04 { // Offset: 0x00000220 Length: 0x000000B0 } .module Hash04.dll -// MVID: {5F1FBE49-9642-7838-A745-038349BE1F5F} +// MVID: {60BE1F16-9642-7838-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06790000 +// Image base: 0x05A90000 // =============== CLASS MEMBERS DECLARATION =================== @@ -67,7 +67,7 @@ .locals init ([0] int32 x, [1] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,25 'C:\\kevinransom\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash04.fsx' + .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash04.fsx' IL_0000: ldc.i4.1 IL_0001: stloc.0 .line 7,7 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash05.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash05.il.bsl index 50ea47e8580..c2c0f3a2624 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash05.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash05.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Hash05 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Hash05 { - // Offset: 0x00000000 Length: 0x000006E0 + // Offset: 0x00000000 Length: 0x000006D0 } .mresource public FSharpOptimizationData.Hash05 { - // Offset: 0x000006E8 Length: 0x000003B1 + // Offset: 0x000006D8 Length: 0x000003B1 } .module Hash05.dll -// MVID: {59B18AEE-9642-7857-A745-0383EE8AB159} +// MVID: {60BE1F16-9642-7857-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01AC0000 +// Image base: 0x067C0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -187,7 +187,7 @@ [4] int32 V_4, [5] int32 V_5) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash05.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash05.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash06.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash06.il.bsl index df45d5ddbdb..e89af0b76f0 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash06.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash06.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Hash06 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Hash06 { - // Offset: 0x00000000 Length: 0x000006E1 + // Offset: 0x00000000 Length: 0x000006D1 } .mresource public FSharpOptimizationData.Hash06 { - // Offset: 0x000006E8 Length: 0x000003B2 + // Offset: 0x000006D8 Length: 0x000003B2 } .module Hash06.dll -// MVID: {59B18AEE-9642-78F2-A745-0383EE8AB159} +// MVID: {60BE1F16-9642-78F2-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01040000 +// Image base: 0x05280000 // =============== CLASS MEMBERS DECLARATION =================== @@ -187,7 +187,7 @@ [4] int32 V_4, [5] int32 V_5) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash06.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash06.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash07.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash07.il.bsl index b57640a2818..ab4e803086f 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash07.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash07.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Hash07 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Hash07 { - // Offset: 0x00000000 Length: 0x0000021A + // Offset: 0x00000000 Length: 0x00000216 } .mresource public FSharpOptimizationData.Hash07 { // Offset: 0x00000220 Length: 0x000000AA } .module Hash07.dll -// MVID: {59B18AEE-9642-7811-A745-0383EE8AB159} +// MVID: {60BE1F16-9642-7811-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x010A0000 +// Image base: 0x06740000 // =============== CLASS MEMBERS DECLARATION =================== @@ -62,7 +62,7 @@ .locals init ([0] int32 x, [1] int32 i) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash07.fsx' + .line 5,5 : 8,25 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash07.fsx' IL_0000: ldc.i4.1 IL_0001: stloc.0 .line 6,6 : 8,32 '' diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash08.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash08.il.bsl index a0945b3885d..b2d3f9d1c9d 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash08.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash08.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Hash08 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Hash08 { - // Offset: 0x00000000 Length: 0x000006D3 + // Offset: 0x00000000 Length: 0x000006C3 } .mresource public FSharpOptimizationData.Hash08 { - // Offset: 0x000006D8 Length: 0x000003B3 + // Offset: 0x000006C8 Length: 0x000003B3 } .module Hash08.dll -// MVID: {59B18AEE-9642-77BC-A745-0383EE8AB159} +// MVID: {60BE1F16-9642-77BC-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01AA0000 +// Image base: 0x06A70000 // =============== CLASS MEMBERS DECLARATION =================== @@ -130,7 +130,7 @@ [2] int32 V_2, [3] int32 V_3) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash08.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash08.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.bsl index df7b115d207..dec226fde70 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash09.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Hash09 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Hash09 { - // Offset: 0x00000000 Length: 0x0000088E + // Offset: 0x00000000 Length: 0x0000087E } .mresource public FSharpOptimizationData.Hash09 { - // Offset: 0x00000898 Length: 0x00000686 + // Offset: 0x00000888 Length: 0x00000680 } .module Hash09.dll -// MVID: {59B18AEE-9642-77DB-A745-0383EE8AB159} +// MVID: {60BE1F16-9642-77DB-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00690000 +// Image base: 0x071B0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -187,7 +187,7 @@ [4] !a V_4, [5] !a V_5) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash09.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash09.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash10.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash10.il.bsl index 20c3ceeb8f6..a592e836742 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash10.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash10.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Hash10 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Hash10 { - // Offset: 0x00000000 Length: 0x00000219 + // Offset: 0x00000000 Length: 0x00000215 } .mresource public FSharpOptimizationData.Hash10 { // Offset: 0x00000220 Length: 0x000000A9 } .module Hash10.dll -// MVID: {59B18AEE-9661-78B4-A745-0383EE8AB159} +// MVID: {60BE1F16-9661-78B4-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01080000 +// Image base: 0x00BB0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,7 +63,7 @@ [1] int32 i, [2] int32 V_2) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 6,6 : 8,36 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash10.fsx' + .line 6,6 : 8,36 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash10.fsx' IL_0000: ldc.i4.0 IL_0001: ldc.i4.1 IL_0002: ldc.i4.s 100 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash11.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash11.il.bsl index f4eb5020175..e01d5bc6aad 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash11.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash11.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Hash11 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Hash11 { - // Offset: 0x00000000 Length: 0x00000219 + // Offset: 0x00000000 Length: 0x00000215 } .mresource public FSharpOptimizationData.Hash11 { // Offset: 0x00000220 Length: 0x000000A9 } .module Hash11.dll -// MVID: {59B18AEE-9661-78D3-A745-0383EE8AB159} +// MVID: {60BE1F16-9661-78D3-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x002D0000 +// Image base: 0x06C60000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,7 +63,7 @@ [1] int32 i, [2] int32 V_2) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 6,6 : 8,32 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash11.fsx' + .line 6,6 : 8,32 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash11.fsx' IL_0000: ldc.i4.0 IL_0001: ldc.i4.1 IL_0002: ldc.i4.s 100 diff --git a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.bsl b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.bsl index 9c5bfb73cf3..458e033bb07 100644 --- a/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/GenericComparison/Hash12.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Hash12 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.Hash12 { - // Offset: 0x00000000 Length: 0x00000A98 + // Offset: 0x00000000 Length: 0x00000A88 } .mresource public FSharpOptimizationData.Hash12 { - // Offset: 0x00000AA0 Length: 0x00000585 + // Offset: 0x00000A90 Length: 0x00000585 } .module Hash12.dll -// MVID: {59B18AEE-9661-796E-A745-0383EE8AB159} +// MVID: {60BE1F16-9661-796E-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01080000 +// Image base: 0x00BB0000 // =============== CLASS MEMBERS DECLARATION =================== @@ -187,7 +187,7 @@ [4] int32 V_4, [5] int32 V_5) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\GenericComparison\\Hash12.fsx' + .line 16707566,16707566 : 0,0 'C:\\GitHub\\dsyme\\fsharp\\tests\\fsharpqa\\source\\Optimizations\\GenericComparison\\Hash12.fsx' IL_0000: ldarg.0 IL_0001: ldnull IL_0002: cgt.un diff --git a/tests/fsharpqa/Source/Optimizations/Inlining/Match01.il.bsl b/tests/fsharpqa/Source/Optimizations/Inlining/Match01.il.bsl index aa979cf89ae..cc844fbd85e 100644 --- a/tests/fsharpqa/Source/Optimizations/Inlining/Match01.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/Inlining/Match01.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Match01 { @@ -25,20 +25,20 @@ } .mresource public FSharpSignatureData.Match01 { - // Offset: 0x00000000 Length: 0x000006F6 + // Offset: 0x00000000 Length: 0x000006E6 } .mresource public FSharpOptimizationData.Match01 { - // Offset: 0x00000700 Length: 0x000003B7 + // Offset: 0x000006F0 Length: 0x000003B7 } .module Match01.dll -// MVID: {59B18AF8-FAFE-C8E4-A745-0383F88AB159} +// MVID: {60BE1F16-FAFE-C8E4-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x01790000 +// Image base: 0x09680000 // =============== CLASS MEMBERS DECLARATION =================== diff --git a/tests/fsharpqa/Source/Optimizations/Inlining/Match02.il.bsl b/tests/fsharpqa/Source/Optimizations/Inlining/Match02.il.bsl index a22def741ec..92c0efac716 100644 --- a/tests/fsharpqa/Source/Optimizations/Inlining/Match02.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/Inlining/Match02.il.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.8.3928.0 // Copyright (c) Microsoft Corporation. All rights reserved. @@ -13,7 +13,7 @@ .assembly extern FSharp.Core { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: - .ver 4:4:1:0 + .ver 5:0:0:0 } .assembly Match02 { @@ -25,20 +25,20 @@ } .mresource public FSharpSignatureData.Match02 { - // Offset: 0x00000000 Length: 0x00000490 + // Offset: 0x00000000 Length: 0x00000484 } .mresource public FSharpOptimizationData.Match02 { - // Offset: 0x00000498 Length: 0x000002EE + // Offset: 0x00000488 Length: 0x000002EE } .module Match02.dll -// MVID: {59B18AF8-6125-4D81-A745-0383F88AB159} +// MVID: {60BE1F16-6125-4D81-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x015D0000 +// Image base: 0x06770000 // =============== CLASS MEMBERS DECLARATION =================== diff --git a/tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.il.bsl b/tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.il.bsl index 164a3ee6567..32e3a02a228 100644 --- a/tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/Inlining/StructUnion01.il.bsl @@ -32,13 +32,13 @@ // Offset: 0x00000880 Length: 0x00000421 } .module StructUnion01.dll -// MVID: {60B6A4C9-D3E9-6B24-A745-0383C9A4B660} +// MVID: {60BE1F16-D3E9-6B24-A745-0383161FBE60} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x06CE0000 +// Image base: 0x065C0000 // =============== CLASS MEMBERS DECLARATION =================== diff --git a/tests/walkthroughs/DebugStepping/TheBigFileOfDebugStepping.fsx b/tests/walkthroughs/DebugStepping/TheBigFileOfDebugStepping.fsx index b5dcc2d6f0b..52800ce3c93 100644 --- a/tests/walkthroughs/DebugStepping/TheBigFileOfDebugStepping.fsx +++ b/tests/walkthroughs/DebugStepping/TheBigFileOfDebugStepping.fsx @@ -1,6 +1,5 @@ // Instructions: -// Debug\net40\bin\fsc.exe --debug+ --tailcalls- --optimize- tests\walkthroughs\DebugStepping\TheBigFileOfDebugStepping.fsx -// Release\net40\bin\fsc.exe --debug+ --tailcalls- --optimize- tests\walkthroughs\DebugStepping\TheBigFileOfDebugStepping.fsx +// artifacts\bin\fsc\Debug\net472\fsc.exe --debug+ --tailcalls- --optimize- --langversion:preview tests\walkthroughs\DebugStepping\TheBigFileOfDebugStepping.fsx // devenv /debugexe TheBigFileOfDebugStepping.exe // // Repeat the above with @@ -11,6 +10,7 @@ // - Different visual debuggers open System +open System.Threading.Tasks type U2 = U2 of int * int @@ -34,15 +34,15 @@ let rec TailcallRecursionTest2 (U2(a,b)) = TailcallRecursionTest2 (U2(a-1,b-1)) // check the 'a' and 'b' update correctly let AsyncExpressionSteppingTest1 () = - async { printfn "hello" - printfn "stuck in the middle" - printfn "goodbye"} + async { Console.WriteLine "hello" + Console.WriteLine "stuck in the middle" + Console.WriteLine "goodbye"} let AsyncExpressionSteppingTest2 () = let x = ref 0 async { while !x < 4 do incr x - printfn "hello" } + Console.WriteLine "hello" } let AsyncExpressionSteppingTest3 () = @@ -62,17 +62,17 @@ let AsyncExpressionSteppingTest4 () = return z finally incr x - printfn "done" } + Console.WriteLine "done" } let es = [3;4;5] let AsyncExpressionSteppingTest5 () = async { for x in es do - printfn "hello" - printfn "hello 2" + Console.WriteLine "hello" + Console.WriteLine "hello 2" for x in es do - printfn "goodbye" - printfn "goodbye 2" } + Console.WriteLine "goodbye" + Console.WriteLine "goodbye 2" } let f2 () = @@ -123,9 +123,9 @@ let ListExpressionSteppingTest1 () = [ yield 1 ] let ListExpressionSteppingTest2 () = - [ printfn "hello" + [ Console.WriteLine "hello" yield 1 - printfn "goodbye" + Console.WriteLine "goodbye" yield 2] @@ -133,7 +133,7 @@ let ListExpressionSteppingTest3 () = let x = ref 0 [ while !x < 4 do incr x - printfn "hello" + Console.WriteLine "hello" yield x ] @@ -157,15 +157,15 @@ let ListExpressionSteppingTest5 () = yield z finally incr x - printfn "done" ] + Console.WriteLine "done" ] let ListExpressionSteppingTest6 () = [ for x in es do - printfn "hello" + Console.WriteLine "hello" yield x for x in es do - printfn "goodbye" + Console.WriteLine "goodbye" yield x ] let ListExpressionSteppingTest7 () = @@ -191,9 +191,9 @@ let SeqExpressionSteppingTest1 () = let SeqExpressionSteppingTest2 () = - seq { printfn "hello" + seq { Console.WriteLine "hello" yield 1 - printfn "goodbye" + Console.WriteLine "goodbye" yield 2 } @@ -202,7 +202,7 @@ let SeqExpressionSteppingTest3 () = let x = ref 0 seq { while !x < 4 do incr x - printfn "hello" + Console.WriteLine "hello" yield x } @@ -227,15 +227,15 @@ let SeqExpressionSteppingTest5 () = yield z finally incr x - printfn "done" } + Console.WriteLine "done" } let SeqExpressionSteppingTest6 () = seq { for x in es do - printfn "hello" + Console.WriteLine "hello" yield x for x in es do - printfn "goodbye" + Console.WriteLine "goodbye" yield x } @@ -362,8 +362,8 @@ let OuterWithNonGenericInnerWithCapture x list = let TestFunction1() = - printfn "Hello"; - printfn "World"; + Console.WriteLine "Hello"; + Console.WriteLine "World"; 3+4 @@ -418,17 +418,17 @@ type C(x:int,y:int) = let TestFunction19(inp) = let c1 = C(inp,inp) let c2 = C(inp,inp) - printfn "c1 = %A, c2 = %A" c1 c2 + Console.WriteLine $"c1 = {c1}, c2 = {c2}" let TestFunction1_0() = - printfn "Hello"; - printfn "World"; + Console.WriteLine "Hello"; + Console.WriteLine "World"; 3+4 let TestFunction2() = let x = TestFunction1_0() - printfn "Hello"; - printfn "World" + Console.WriteLine "Hello"; + Console.WriteLine "World" type D(x:int,y:int) = @@ -441,27 +441,27 @@ type D(x:int,y:int) = let TestFunction20(inp) = let d1 = D(inp,inp) let d2 = D(inp,inp) - printfn "d1 = %A, d2 = %A" d1 d2 + Console.WriteLine $"done d1 = {d1}, d2 = {d2}" let TestFunction21(U2(a,b)) = - printfn "a = %A, a = %A" a b + Console.WriteLine $"a = {a}, b = {b}" let TestFunction1_1() = - printfn "Hello"; - printfn "World"; + Console.WriteLine "Hello"; + Console.WriteLine "World"; 3+4 let TestFunction3() = try let x = TestFunction1_1() - printfn "Hello"; + Console.WriteLine "Hello"; with _ -> - printfn "World" + Console.WriteLine "World" let TestFunction1_2() = - printfn "Hello"; - printfn "World"; + Console.WriteLine "Hello"; + Console.WriteLine "World"; 3+4 let TestFunction3b() = @@ -469,11 +469,11 @@ let TestFunction3b() = let x = TestFunction1_2() failwith "hello" with Failure _ -> - printfn "World" + Console.WriteLine "World" let TestFunction1_3() = - printfn "Hello"; - printfn "World"; + Console.WriteLine "Hello"; + Console.WriteLine "World"; 3+4 let TestFunction3c() = @@ -481,43 +481,43 @@ let TestFunction3c() = let x = TestFunction1_3() failwith "hello" with Failure msg when msg = "hello" -> - printfn "World" + Console.WriteLine "World" let TestFunction1_4() = - printfn "Hello"; - printfn "World"; + Console.WriteLine "Hello"; + Console.WriteLine "World"; 3+4 let TestFunction4() = try let x = TestFunction1_4() - printfn "Hello"; + Console.WriteLine "Hello"; finally - printfn "World" + Console.WriteLine "World" let TestFunction1_5() = - printfn "Hello"; - printfn "World"; + Console.WriteLine "Hello"; + Console.WriteLine "World"; 3+4 let TestFunction5() = let x = let y = TestFunction1_5() - printfn "Hello"; + Console.WriteLine "Hello"; y + y x + x let TestFunction1_6() = - printfn "Hello"; - printfn "World"; + Console.WriteLine "Hello"; + Console.WriteLine "World"; 3+4 let TestFunction6() = let f() = let y = TestFunction1_6() - printfn "Hello"; + Console.WriteLine "Hello"; y + y f() + f() @@ -626,6 +626,174 @@ let LocalValueShadowsArgument2 x = null // breakpoint 2 () +let TaskExpressionSteppingTest0 () = + task { Console.WriteLine "hello" + Console.WriteLine "stuck in the middle" + Console.WriteLine "goodbye"} + +let TaskExpressionSteppingTest1 () = + task { Console.WriteLine "hello" + Console.WriteLine "stuck in the middle" + do! Task.Delay 100 + Console.WriteLine "goodbye"} + +let TaskExpressionSteppingTest2 () = + let x = ref 0 + task { while !x < 4 do + incr x + Console.WriteLine "hello" } + +let TaskExpressionSteppingTest3 () = + task { let x = ref 0 + incr x + let y = ref 0 + incr y + let z = !x + !y + return z } + +let TaskExpressionSteppingTest4 () = + task { let x = ref 0 + try + let y = ref 0 + incr y + let z = !x + !y + return z + finally + incr x + Console.WriteLine "done" } + +let TaskExpressionSteppingTest5 () = + task { for x in es do + Console.WriteLine "hello" + Console.WriteLine "hello 2" + for x in es do + Console.WriteLine "goodbye" + Console.WriteLine "goodbye 2" } + +let tf2 () = + task { let x = ref 0 + incr x + let y = ref 0 + incr y + let z = !x + !y + return z } + +let TaskExpressionSteppingTest6b () = + task { let! x1 = tf2() + let! x2 = tf2() + let! x3 = tf2() + let y = ref 0 + incr y + let! x4 = tf2() + let z = x1 + !y + x4 + return z } + +let TaskExpressionSteppingTest7a () = + task { let x = ref 0 + try + let y = ref 0 + incr y + let z = !x + !y + return z + with exn -> + incr x + Console.WriteLine "done" + return 0 } + +let TaskExpressionSteppingTest7b () = + task { let x = ref 0 + try + let y = ref 0 + incr y + failwith "fail" + let z = !x + !y + return z + with exn -> + incr x + Console.WriteLine "done" + return 0 } + +let TaskBreakpoints1 () = + task { let! res1 = + tf2() + let! res2 = + match 1 with + | 1 -> tf2() + | _ -> tf2() + let! res3 = + match 1 with + | 1 -> + let x = + match 4 with + | 2 -> tf2() + | _ -> tf2() + tf2() + | _ -> + let x = + match 4 with + | 2 -> tf2() + | _ -> tf2() + tf2() + return () } + +module InlinedCode = + // NOTE: you can't place breakpoints in this method and hit them in either Debug and Release code + let inline bodyRunner z body = + let x = 1 + z + printfn "running" + body x + body x + + let test() = + let bodyWrapper = + let x = 1 + System.Random().Next() + bodyRunner 3 (fun n -> + // MANUAL TEST: check you can place breakpoint here and hit it in both Debug and Release code + printfn "line1, x = %d" x + // MANUAL TEST: check you can place breakpoint here and hit it in both Debug and Release code + printfn "line2, n = %d" n) + + let bodyWrapper2 = + // TEST: check you can place breakpoint here and hit it in both Debug and Release code + let x = 1 + System.Random().Next() + bodyRunner 3 <| (fun n -> + // MANUAL TEST: check you can place breakpoint here and hit it in both Debug and Release code + printfn "line1, x = %d" x + // MANUAL TEST: check you can place breakpoint here and hit it in both Debug and Release code + printfn "line2, n = %d" n) + () + +module Pipelined = + let testListPipeline() = + let data = [ 1 .. 5 ] + + // MANUAL TEST: check stepping through this looks ok + let newData = + data + |> List.filter (fun x -> + // MANUAL TEST: check you can place breakpoint here and hit it in both Debug and Release code + x > 3) + |> List.map (fun x -> + // MANUAL TEST: check you can place breakpoint here and hit it in both Debug and Release code + x * x) + + printfn "%A" newData + + let testArrayPipeline() = + let data = [| 1 .. 5 |] + + let newData = + data + |> Array.filter (fun x -> + // MANUAL TEST: check you can place breakpoint here and hit it in both Debug and Release code + x > 3) + |> Array.map (fun x -> + // MANUAL TEST: check you can place breakpoint here and hit it in both Debug code + // TODO: surprisingly no breakpoint hit here in release code + x * x) + + printfn "%A" newData + TailcallRecursionTest1 3 TailcallRecursionTest2 (U2(3,4)) SteppingMatch01 (Choice1Of2 3) @@ -705,3 +873,20 @@ InnerFunctionDefinitionHadTwoBreakpoints "aaaa" |> ignore InnerRecursiveFunctionDefinitionHadTwoBreakpoints "aaaa" |> ignore LocalValueShadowsArgument1 "123" LocalValueShadowsArgument2 "123" + +module Task = + let RunSynchronously (t: System.Threading.Tasks.Task<_>) = t.Wait(); t.Result + +TaskExpressionSteppingTest0() |> Task.RunSynchronously +TaskExpressionSteppingTest1() |> Task.RunSynchronously +TaskExpressionSteppingTest2() |> Task.RunSynchronously +TaskExpressionSteppingTest3() |> Task.RunSynchronously +TaskExpressionSteppingTest4() |> Task.RunSynchronously +TaskExpressionSteppingTest5() |> Task.RunSynchronously +TaskExpressionSteppingTest6b() |> Task.RunSynchronously +TaskExpressionSteppingTest7a() |> Task.RunSynchronously +TaskExpressionSteppingTest7b() |> Task.RunSynchronously +TaskBreakpoints1() |> Task.RunSynchronously +InlinedCode.test() +Pipelined.testListPipeline() +Pipelined.testArrayPipeline()