Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6b0f185

Browse files
author
dotnet-automerge-bot
authored
Merge pull requestdotnet#5643 from Microsoft/merges/master-to-dev16.0
Merge master to dev16.0
2 parents1177340 +8fbd6bf commit6b0f185

File tree

27 files changed

+5371
-6523
lines changed

27 files changed

+5371
-6523
lines changed

‎src/fsharp/FSharp.Core/string.fs‎

Lines changed: 54 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,57 +12,59 @@ namespace Microsoft.FSharp.Core
1212
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
1313
[<RequireQualifiedAccess>]
1414
moduleString=
15-
16-
let inlineemptyIfNull str=
17-
match strwith
18-
|null-> String.Empty
19-
|_-> str
20-
2115
[<CompiledName("Concat")>]
2216
letconcat sep(strings:seq<string>)=
2317
String.Join(sep, strings)
2418

2519
[<CompiledName("Iterate")>]
2620
letiter(action:(char-> unit))(str:string)=
27-
letstr= emptyIfNullstr
28-
for i=0to str.Length-1do
29-
action str.[i]
21+
ifnot(String.IsNullOrEmptystr)then
22+
for i=0to str.Length-1do
23+
action str.[i]
3024

3125
[<CompiledName("IterateIndexed")>]
3226
letiteri action(str:string)=
33-
letstr= emptyIfNullstr
34-
letf= OptimizedClosures.FSharpFunc<_,_,_>.Adapt(action)
35-
for i=0to str.Length-1do
36-
f.Invoke(i, str.[i])
27+
ifnot(String.IsNullOrEmptystr)then
28+
letf= OptimizedClosures.FSharpFunc<_,_,_>.Adapt(action)
29+
for i=0to str.Length-1do
30+
f.Invoke(i, str.[i])
3731

3832
[<CompiledName("Map")>]
3933
letmap(mapping:char->char)(str:string)=
40-
letstr= emptyIfNull str
41-
letres= StringBuilder str.Length
42-
str|> iter(fun c-> res.Append(mapping c)|> ignore)
43-
res.ToString()
34+
if String.IsNullOrEmpty strthen
35+
String.Empty
36+
else
37+
letres= StringBuilder str.Length
38+
str|> iter(fun c-> res.Append(mapping c)|> ignore)
39+
res.ToString()
4440

4541
[<CompiledName("MapIndexed")>]
4642
letmapi(mapping:int->char->char)(str:string)=
47-
letstr= emptyIfNull str
48-
letres= StringBuilder str.Length
49-
letf= OptimizedClosures.FSharpFunc<_,_,_>.Adapt(mapping)
50-
str|> iteri(fun i c-> res.Append(f.Invoke(i, c))|> ignore)
51-
res.ToString()
43+
if String.IsNullOrEmpty strthen
44+
String.Empty
45+
else
46+
letres= StringBuilder str.Length
47+
letf= OptimizedClosures.FSharpFunc<_,_,_>.Adapt(mapping)
48+
str|> iteri(fun i c-> res.Append(f.Invoke(i, c))|> ignore)
49+
res.ToString()
5250

5351
[<CompiledName("Filter")>]
5452
letfilter(predicate:char->bool)(str:string)=
55-
letstr= emptyIfNull str
56-
letres= StringBuilder str.Length
57-
str|> iter(fun c->if predicate cthen res.Append c|> ignore)
58-
res.ToString()
53+
if String.IsNullOrEmpty strthen
54+
String.Empty
55+
else
56+
letres= StringBuilder str.Length
57+
str|> iter(fun c->if predicate cthen res.Append c|> ignore)
58+
res.ToString()
5959

6060
[<CompiledName("Collect")>]
6161
letcollect(mapping:char->string)(str:string)=
62-
letstr= emptyIfNull str
63-
letres= StringBuilder str.Length
64-
str|> iter(fun c-> res.Append(mapping c)|> ignore)
65-
res.ToString()
62+
if String.IsNullOrEmpty strthen
63+
String.Empty
64+
else
65+
letres= StringBuilder str.Length
66+
str|> iter(fun c-> res.Append(mapping c)|> ignore)
67+
res.ToString()
6668

6769
[<CompiledName("Initialize")>]
6870
letinit(count:int)(initializer:int->string)=
@@ -75,25 +77,34 @@ namespace Microsoft.FSharp.Core
7577
[<CompiledName("Replicate")>]
7678
letreplicate(count:int)(str:string)=
7779
if count<0then invalidArgInputMustBeNonNegative"count" count
78-
letstr= emptyIfNull str
79-
letres= StringBuilder str.Length
80-
for i=0to count-1do
81-
res.Append str|> ignore
82-
res.ToString()
80+
81+
if String.IsNullOrEmpty strthen
82+
String.Empty
83+
else
84+
letres= StringBuilder(count* str.Length)
85+
for i=0to count-1do
86+
res.Append str|> ignore
87+
res.ToString()
8388

8489
[<CompiledName("ForAll")>]
8590
letforall predicate(str:string)=
86-
letstr= emptyIfNull str
87-
let reccheck i=(i>= str.Length)||(predicate str.[i]&& check(i+1))
88-
check0
91+
if String.IsNullOrEmpty strthen
92+
true
93+
else
94+
let reccheck i=(i>= str.Length)||(predicate str.[i]&& check(i+1))
95+
check0
8996

9097
[<CompiledName("Exists")>]
9198
letexists predicate(str:string)=
92-
letstr= emptyIfNull str
93-
let reccheck i=(i< str.Length)&&(predicate str.[i]|| check(i+1))
94-
check0
99+
if String.IsNullOrEmpty strthen
100+
false
101+
else
102+
let reccheck i=(i< str.Length)&&(predicate str.[i]|| check(i+1))
103+
check0
95104

96105
[<CompiledName("Length")>]
97106
letlength(str:string)=
98-
letstr= emptyIfNull str
99-
str.Length
107+
if String.IsNullOrEmpty strthen
108+
0
109+
else
110+
str.Length

‎src/fsharp/LowerCallsAndSeqs.fs‎

Lines changed: 84 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,18 @@ type LoweredSeqFirstPhaseResult =
8484
{/// The code to run in the second phase, to rebuild the expressions, once all code labels and their mapping to program counters have been determined
8585
/// 'nextVar' is the argument variable for the GenerateNext method that represents the byref argument that holds the "goto" destination for a tailcalling sequence expression
8686
phase2:((* pc:*) ValRef*(* current:*) ValRef*(* nextVar:*) ValRef* Map<ILCodeLabel,int>-> Expr* Expr* Expr)
87+
8788
/// The labels allocated for one portion of the sequence expression
8889
labels:int list
90+
8991
/// any actual work done in Close
9092
significantClose:bool
9193

9294
/// The state variables allocated for one portion of the sequence expression (i.e. the local let-bound variables which become state variables)
93-
stateVars:ValRef list}
95+
stateVars:ValRef list
96+
97+
/// The vars captured by the non-synchronous path
98+
capturedVars:FreeVars}
9499

95100
letisVarFreeInExpr v e= Zset.contains v(freeInExpr CollectTyparsAndLocals e).FreeLocals
96101

@@ -174,6 +179,17 @@ let LowerSeqExpr g amap overallExpr =
174179
| Expr.App(Expr.Val(vref,_,_),_f0ty,[elemTy],[e],_m)when valRefEq g vref g.seq_vref-> Some(e,elemTy)
175180
|_-> None
176181

182+
letRepresentBindingAsLocal(bind:Binding)res2 m=
183+
// printfn "found letrec state variable %s" bind.Var.DisplayName
184+
{ res2with
185+
phase2=(fun ctxt->
186+
letgenerate2,dispose2,checkDispose2= res2.phase2 ctxt
187+
letgenerate= mkLetBind m bind generate2
188+
letdispose= dispose2
189+
letcheckDispose= checkDispose2
190+
generate,dispose,checkDispose)
191+
stateVars= res2.stateVars}
192+
177193
letRepresentBindingAsStateMachineLocal(bind:Binding)res2 m=
178194
// printfn "found letrec state variable %s" bind.Var.DisplayName
179195
let(TBind(v,e,sp))= bind
@@ -243,17 +259,28 @@ let LowerSeqExpr g amap overallExpr =
243259
labels=[label]
244260
stateVars=[]
245261
significantClose=false
262+
capturedVars= emptyFreeVars
246263
}
247264

248-
| SeqDelay(e,_elemTy)->
265+
| SeqDelay(delayedExpr,_elemTy)->
249266
// printfn "found Seq.delay"
250-
Lower isWholeExpr isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel e// note, using 'isWholeExpr' here prevents 'seq { yield! e }' and 'seq { 0 .. 1000 }' from being compiled
267+
// note, using 'isWholeExpr' here prevents 'seq { yield! e }' and 'seq { 0 .. 1000 }' from being compiled
268+
Lower isWholeExpr isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel delayedExpr
251269

252270
| SeqAppend(e1,e2,m)->
253271
// printfn "found Seq.append"
254-
match Lowerfalsefalse noDisposeContinuationLabel currentDisposeContinuationLabel e1,
255-
Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel e2with
272+
letres1= Lowerfalsefalse noDisposeContinuationLabel currentDisposeContinuationLabel e1
273+
letres2= Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel e2
274+
match res1, res2with
256275
| Some res1, Some res2->
276+
277+
letcapturedVars=
278+
if res1.labels.IsEmptythen
279+
res2.capturedVars
280+
else
281+
// All of 'e2' is needed after resuming at any of the labels
282+
unionFreeVars res1.capturedVars(freeInExpr CollectLocals e2)
283+
257284
Some{ phase2=(fun ctxt->
258285
letgenerate1,dispose1,checkDispose1= res1.phase2 ctxt
259286
letgenerate2,dispose2,checkDispose2= res2.phase2 ctxt
@@ -265,29 +292,43 @@ let LowerSeqExpr g amap overallExpr =
265292
generate,dispose,checkDispose)
266293
labels= res1.labels@ res2.labels
267294
stateVars= res1.stateVars@ res2.stateVars
268-
significantClose= res1.significantClose|| res2.significantClose}
295+
significantClose= res1.significantClose|| res2.significantClose
296+
capturedVars= capturedVars}
269297
|_->
270298
None
271299

272-
| SeqWhile(e1,e2,m)->
300+
| SeqWhile(guardExpr,bodyExpr,m)->
273301
// printfn "found Seq.while"
274-
match Lowerfalsefalse noDisposeContinuationLabel currentDisposeContinuationLabel e2with
302+
letresBody= Lowerfalsefalse noDisposeContinuationLabel currentDisposeContinuationLabel bodyExpr
303+
match resBodywith
275304
| Some res2->
305+
letcapturedVars=
306+
if res2.labels.IsEmptythen
307+
res2.capturedVars// the whole loopis synchronous, no labels
308+
else
309+
freeInExpr CollectLocals expr// everything is needed on subsequent iterations
310+
276311
Some{ phase2=(fun ctxt->
277312
letgenerate2,dispose2,checkDispose2= res2.phase2 ctxt
278-
letgenerate= mkWhile g(SequencePointAtWhileLoope1.Range,NoSpecialWhileLoopMarker,e1,generate2,m)
313+
letgenerate= mkWhile g(SequencePointAtWhileLoopguardExpr.Range,NoSpecialWhileLoopMarker,guardExpr,generate2,m)
279314
letdispose= dispose2
280315
letcheckDispose= checkDispose2
281316
generate,dispose,checkDispose)
282317
labels= res2.labels
283318
stateVars= res2.stateVars
284-
significantClose= res2.significantClose}
319+
significantClose= res2.significantClose
320+
capturedVars= capturedVars}
285321
|_->
286322
None
287323

288324
| SeqUsing(resource,v,body,elemTy,m)->
289325
// printfn "found Seq.using"
290-
Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel(mkLet(SequencePointAtBinding body.Range) m v resource(mkCallSeqFinally g m elemTy body(mkUnitDelayLambda g m(mkCallDispose g m v.Type(exprForVal m v)))))
326+
letreduction=
327+
mkLet(SequencePointAtBinding body.Range) m v resource
328+
(mkCallSeqFinally g m elemTy body
329+
(mkUnitDelayLambda g m
330+
(mkCallDispose g m v.Type(exprForVal m v))))
331+
Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel reduction
291332

292333
| SeqFor(inp,v,body,genElemTy,m)->
293334
// printfn "found Seq.for"
@@ -298,18 +339,21 @@ let LowerSeqExpr g amap overallExpr =
298339
// while enum.MoveNext() do
299340
// let v = enum.Current
300341
// body ]]
301-
Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel
302-
(mkCallSeqUsing g m inpEnumTy genElemTy(callNonOverloadedMethod g amap m"GetEnumerator"(mkSeqTy g inpElemTy)[inp])
303-
(mkLambdaNoType g m enumv
342+
letreduction=
343+
mkCallSeqUsing g m inpEnumTy genElemTy(callNonOverloadedMethod g amap m"GetEnumerator"(mkSeqTy g inpElemTy)[inp])
344+
(mkLambdaNoType g m enumv
304345
(mkCallSeqGenerated g m genElemTy(mkUnitDelayLambda g m(callNonOverloadedMethod g amap m"MoveNext" inpEnumTy[enume]))
305346
(mkInvisibleLet m v(callNonOverloadedMethod g amap m"get_Current" inpEnumTy[enume])
306-
(mkCoerceIfNeeded g(mkSeqTy g genElemTy)(tyOfExpr g body) body)))))
347+
(mkCoerceIfNeeded g(mkSeqTy g genElemTy)(tyOfExpr g body) body))))
348+
Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel reduction
307349

308350
| SeqTryFinally(e1,compensation,m)->
309351
// printfn "found Seq.try/finally"
310352
letinnerDisposeContinuationLabel= IL.generateCodeLabel()
311-
match Lowerfalsefalse noDisposeContinuationLabel innerDisposeContinuationLabel e1with
353+
letresBody= Lowerfalsefalse noDisposeContinuationLabel innerDisposeContinuationLabel e1
354+
match resBodywith
312355
| Some res1->
356+
letcapturedVars= unionFreeVars res1.capturedVars(freeInExpr CollectLocals compensation)
313357
Some{ phase2=(fun((pcv,_currv,_,pcMap)asctxt)->
314358
letgenerate1,dispose1,checkDispose1= res1.phase2 ctxt
315359
letgenerate=
@@ -348,7 +392,8 @@ let LowerSeqExpr g amap overallExpr =
348392
generate,dispose,checkDispose)
349393
labels= innerDisposeContinuationLabel:: res1.labels
350394
stateVars= res1.stateVars
351-
significantClose=true}
395+
significantClose=true
396+
capturedVars= capturedVars}
352397
|_->
353398
None
354399

@@ -361,7 +406,8 @@ let LowerSeqExpr g amap overallExpr =
361406
generate,dispose,checkDispose)
362407
labels=[]
363408
stateVars=[]
364-
significantClose=false}
409+
significantClose=false
410+
capturedVars= emptyFreeVars}
365411

366412
| Expr.Sequential(x1,x2,NormalSeq,ty,m)->
367413
match Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel x2with
@@ -376,13 +422,18 @@ let LowerSeqExpr g amap overallExpr =
376422
generate,dispose,checkDispose)}
377423
| None-> None
378424

379-
| Expr.Let(bind,e2,m,_)
425+
| Expr.Let(bind,bodyExpr,m,_)
380426
// Restriction: compilation of sequence expressions containing non-toplevel constrained generic functions is not supported
381427
when bind.Var.IsCompiledAsTopLevel||not(IsGenericValWithGenericContraints g bind.Var)->
382-
match Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel e2with
428+
429+
letresBody= Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel bodyExpr
430+
match resBodywith
383431
| Some res2->
384432
if bind.Var.IsCompiledAsTopLevelthen
385433
Some(RepresentBindingsAsLifted(mkLetBind m bind) res2)
434+
elifnot(res2.capturedVars.FreeLocals.Contains(bind.Var))then
435+
// printfn "found state variable %s" bind.Var.DisplayName
436+
Some(RepresentBindingAsLocal bind res2 m)
386437
else
387438
// printfn "found state variable %s" bind.Var.DisplayName
388439
Some(RepresentBindingAsStateMachineLocal bind res2 m)
@@ -421,12 +472,18 @@ let LowerSeqExpr g amap overallExpr =
421472
*)
422473
| Expr.Match(spBind,exprm,pt,targets,m,ty)when targets|> Array.forall(fun(TTarget(vs,_e,_spTarget))-> isNil vs)->
423474
// lower all the targets. abandon if any fail to lower
424-
lettgl= targets|> Array.map(fun(TTarget(_vs,e,_spTarget))-> Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabele)|> Array.toList
475+
lettglArray= targets|> Array.map(fun(TTarget(_vs,targetExpr,_spTarget))-> Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabeltargetExpr)
425476
// LIMITATION: non-trivial pattern matches involving or-patterns or active patterns where bindings can't be
426477
// transferred to the r.h.s. are not yet compiled.
427-
if tgl|> List.forall Option.isSomethen
428-
lettgl= List.map Option.get tgl
478+
if tglArray|> Array.forall Option.isSomethen
479+
lettglArray= Array.map Option.get tglArray
480+
lettgl= Array.toList tglArray
429481
letlabs= tgl|> List.collect(fun res-> res.labels)
482+
let(capturedVars,_)=
483+
((emptyFreeVars,false), Array.zip targets tglArray)
484+
||> Array.fold(fun(fvs,seenLabel)((TTarget(_vs,e,_spTarget)),res)->
485+
if seenLabelthen unionFreeVars fvs(freeInExpr CollectLocals e),true
486+
else res.capturedVars,not res.labels.IsEmpty)
430487
letstateVars= tgl|> List.collect(fun res-> res.stateVars)
431488
letsignificantClose= tgl|> List.exists(fun res-> res.significantClose)
432489
Some{ phase2=(fun ctxt->
@@ -443,7 +500,8 @@ let LowerSeqExpr g amap overallExpr =
443500
generate,dispose,checkDispose)
444501
labels=labs
445502
stateVars= stateVars
446-
significantClose= significantClose}
503+
significantClose= significantClose
504+
capturedVars= capturedVars}
447505
else
448506
None
449507

@@ -502,7 +560,8 @@ let LowerSeqExpr g amap overallExpr =
502560
generate,dispose,checkDispose)
503561
labels=[label]
504562
stateVars=[]
505-
significantClose=false}
563+
significantClose=false
564+
capturedVars= emptyFreeVars}
506565
else
507566
letv,ve= mkCompGenLocal m"v" inpElemTy
508567
Lowerfalse isTailCall noDisposeContinuationLabel currentDisposeContinuationLabel(mkCallSeqCollect g m inpElemTy inpElemTy(mkLambdaNoType g m v(mkCallSeqSingleton g m inpElemTy ve)) arbitrarySeqExpr)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp