Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/Compiler/Optimize/LowerStateMachines.fs
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,17 @@ type LowerStateMachine(g: TcGlobals) =
| 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 }
let envR, _ = BindResumableCodeDefinitions envR defn.Expr
BindResumableCodeDefinitions envR bodyExpr

| Expr.Lambda (valParams = valParams; bodyExpr = bodyExpr; overallType = ty) when isReturnsResumableCodeTy g ty ->
if sm_verbose then printfn "binding fun %A --> %A..." valParams bodyExpr
BindResumableCodeDefinitions env bodyExpr

| Expr.DebugPoint (_, innerExpr) ->
let envR, _ = BindResumableCodeDefinitions env innerExpr
envR, expr

// Eliminate 'if __useResumableCode ...'
| IfUseResumableStateMachinesExpr g (thenExpr, _) ->
if sm_verbose then printfn "eliminating 'if __useResumableCode...'"
Expand Down Expand Up @@ -313,11 +322,14 @@ type LowerStateMachine(g: TcGlobals) =
| Some innerExpr2 -> Some (Expr.DebugPoint (dp, innerExpr2))
| None -> None

| Expr.App _ ->
TryReduceExpr env expr args id

| _ ->
None

// Apply a single expansion of resumable code at the outermost position in an arbitrary expression
let rec TryReduceExpr (env: env) expr args remake =
and 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,97 @@ let compute () =
// multiple invocations to trigger tiered compilation
for i in 1 .. 100 do
compute().Wait ()
"""
|> withOptimize
|> compileExeAndRun
|> shouldSucceed

[<Fact>] // https://github.com/dotnet/fsharp/issues/12839#issuecomment-1292310944
let ``Tasks with a for loop over tuples are statically compilable``() =
FSharp """
module TestProject1

let ret i = task { return i }

let one (f: seq<string * string * int>) = task {
let mutable sum = 0

let! x = ret 1
sum <- sum + x

for name, _whatever, i in f do
let! x = ret i
sum <- sum + x

System.Console.Write name

let! x = ret i
sum <- sum + x

let! x = ret 1
sum <- sum + x

return sum
}

let two (f: seq<string * string * int>) = task {
let mutable sum = 0

let! x = ret 1
sum <- sum + x

for name, _whatever, i in f do
let! x = ret i
sum <- sum + x

System.Console.Write name

let! x = ret 1
sum <- sum + x

return sum
}

let three (f: seq<string * string * int>) = task {
let mutable sum = 0

let! x = ret 1
sum <- sum + x

for name, _whatever, i in f do
let! x = ret i
sum <- sum + x

System.Console.Write name

return sum
}

let four (f: seq<string * int>) = task {
let mutable sum = 0

let! x = ret 5
sum <- sum + x

for name, _i in f do
System.Console.Write name

let! x = ret 1
sum <- sum + x

return sum
}

if (one [ ("", "", 1); ("", "", 2) ]).Result <> 8 then
failwith "unexpected result one"
if (one []).Result <> 2 then
failwith "unexpected result one"
if (two [ ("", "", 2) ]).Result <> 4 then
failwith "unexpected result two"
if (three [ ("", "", 5) ]).Result <> 6 then
failwith "unexpected result three"
if (four [ ("", 10) ]).Result <> 6 then
failwith "unexpected result four"
"""
|> withOptimize
|> compileExeAndRun
Expand Down