@@ -258,7 +258,7 @@ let (|SeqToArray|_|) g expr =
258258
259259module List =
260260 /// Makes an expression that will build a list from an integral range.
261- let mkFromIntegralRange tcVal ( g : TcGlobals ) amap m overallElemTy overallSeqExpr start step finish =
261+ let mkFromIntegralRange tcVal ( g : TcGlobals ) amap m rangeTy overallElemTy rangeExpr start step finish body =
262262 let collectorTy = g.mk_ ListCollector_ ty overallElemTy
263263
264264 /// let collector = ListCollector () in
@@ -267,15 +267,24 @@ module List =
267267 let mkListInit mkLoop =
268268 mkCompGenLetMutableIn m " collector" collectorTy ( mkDefault ( m, collectorTy)) ( fun ( _ , collector ) ->
269269 let reader = InfoReader ( g, amap)
270- let loop = mkLoop ( fun _idxVar loopVar -> mkCallCollectorAdd tcVal g reader m collector loopVar)
270+
271+ let loop =
272+ mkLoop ( fun _idxVar loopVar ->
273+ let body =
274+ body
275+ |> Option.map ( fun ( loopVal , body ) -> mkInvisibleLet m loopVal loopVar body)
276+ |> Option.defaultValue loopVar
277+
278+ mkCallCollectorAdd tcVal g reader m collector body)
279+
271280 let close = mkCallCollectorClose tcVal g reader m collector
272281 mkSequential m loop close
273282 )
274283
275284 mkOptimizedRangeLoop
276285 g
277286 ( m, m, m, DebugPointAtWhile.No)
278- ( overallElemTy , overallSeqExpr )
287+ ( rangeTy , rangeExpr )
279288 ( start, step, finish)
280289 ( fun count mkLoop ->
281290 match count with
@@ -301,7 +310,7 @@ module Array =
301310 | NoCheckOvf
302311
303312 /// Makes an expression that will build an array from an integral range.
304- let mkFromIntegralRange g m overallElemTy overallSeqExpr start step finish =
313+ let mkFromIntegralRange g m rangeTy ilTy overallElemTy rangeExpr start step finish body =
305314 let arrayTy = mkArrayType g overallElemTy
306315
307316 let convToNativeInt ovf expr =
@@ -324,21 +333,21 @@ module Array =
324333 else
325334 expr
326335
327- let ilTy , ilBasicTy =
328- let ty = stripMeasuresFromTy g overallElemTy
329-
330- if typeEquiv g ty g.int32 _ ty then g.ilg.typ _ Int32 , DT _ I4
331- elif typeEquiv g ty g.int64 _ ty then g.ilg.typ _ Int64 , DT _ I8
332- elif typeEquiv g ty g.uint64 _ ty then g.ilg.typ _ UInt64 , DT _ U8
333- elif typeEquiv g ty g.uint32 _ ty then g.ilg.typ _ UInt32 , DT _ U4
334- elif typeEquiv g ty g.nativeint _ ty then g.ilg.typ _ IntPtr , DT _ I
335- elif typeEquiv g ty g.unativeint _ ty then g.ilg.typ _ UIntPtr , DT _ U
336- elif typeEquiv g ty g.int16 _ ty then g.ilg.typ _ Int16 , DT _ I2
337- elif typeEquiv g ty g.uint16 _ ty then g.ilg.typ _ UInt16 , DT _ U2
338- elif typeEquiv g ty g.sbyte _ ty then g.ilg.typ _ SByte , DT _ I1
339- elif typeEquiv g ty g.byte _ ty then g.ilg.typ _ Byte , DT _ U1
340- elif typeEquiv g ty g.char _ ty then g.ilg.typ _ Char , DT _ U2
341- else error ( InternalError ( $ " Unable to find IL type for integral type '{overallElemTy}'. " , m ) )
336+ let stelem =
337+ if ilTy = g.ilg.typ _ Int32 then I _ stelem DT _ I4
338+ elif ilTy = g.ilg.typ _ Int64 then I _ stelem DT _ I8
339+ elif ilTy = g.ilg.typ _ UInt64 then I _ stelem DT _ U8
340+ elif ilTy = g.ilg.typ _ UInt32 then I _ stelem DT _ U4
341+ elif ilTy = g.ilg.typ _ IntPtr then I _ stelem DT _ I
342+ elif ilTy = g.ilg.typ _ UIntPtr then I _ stelem DT _ U
343+ elif ilTy = g.ilg.typ _ Int16 then I _ stelem DT _ I2
344+ elif ilTy = g.ilg.typ _ UInt16 then I _ stelem DT _ U2
345+ elif ilTy = g.ilg.typ _ SByte then I _ stelem DT _ I1
346+ elif ilTy = g.ilg.typ _ Byte then I _ stelem DT _ U1
347+ elif ilTy = g.ilg.typ _ Char then I _ stelem DT _ U2
348+ elif ilTy = g.ilg.typ _ Double then I _ stelem DT _ R8
349+ elif ilTy = g.ilg.typ _ Single then I _ stelem DT _ R4
350+ else I _ stelem _ any ( ILArrayShape.SingleDimensional , ilTy )
342351
343352 /// (# "newarr !0" type ('T) count : 'T array #)
344353 let mkNewArray count =
@@ -356,13 +365,21 @@ module Array =
356365 /// array
357366 let mkArrayInit count mkLoop =
358367 mkCompGenLetIn m " array" arrayTy ( mkNewArray count) ( fun ( _ , array ) ->
359- let loop = mkLoop ( fun idxVar loopVar -> mkAsmExpr ([ I_ stelem ilBasicTy], [], [ array; convToNativeInt NoCheckOvf idxVar; loopVar], [], m))
368+ let loop =
369+ mkLoop ( fun idxVar loopVar ->
370+ let body =
371+ body
372+ |> Option.map ( fun ( loopVal , body ) -> mkInvisibleLet m loopVal loopVar body)
373+ |> Option.defaultValue loopVar
374+
375+ mkAsmExpr ([ stelem], [], [ array; convToNativeInt NoCheckOvf idxVar; body], [], m))
376+
360377 mkSequential m loop array)
361378
362379 mkOptimizedRangeLoop
363380 g
364381 ( m, m, m, DebugPointAtWhile.No)
365- ( overallElemTy , overallSeqExpr )
382+ ( rangeTy , rangeExpr )
366383 ( start, step, finish)
367384 ( fun count mkLoop ->
368385 match count with
@@ -399,7 +416,64 @@ module Array =
399416 )
400417 )
401418
402- let LowerComputedListOrArrayExpr tcVal ( g : TcGlobals ) amap overallExpr =
419+ /// f (); …; Seq.singleton x
420+ ///
421+ /// E.g., in [for x in … do f (); …; yield x]
422+ [<return : Struct>]
423+ let (| SimpleSequential | _ |) g expr =
424+ let rec loop expr cont =
425+ match expr with
426+ | Expr.Sequential ( expr1, DebugPoints ( ValApp g g.seq_ singleton_ vref (_, [ body], _), debug), kind, m) ->
427+ ValueSome ( cont ( expr1, debug body, kind, m))
428+
429+ | Expr.Sequential ( expr1, body, kind, m) ->
430+ loop body ( cont >> fun body -> Expr.Sequential ( expr1, body, kind, m))
431+
432+ | _ -> ValueNone
433+
434+ loop expr Expr.Sequential
435+
436+ /// The representation used for
437+ ///
438+ /// for … in … -> …
439+ ///
440+ /// and
441+ ///
442+ /// for … in … do yield …
443+ [<return : Struct>]
444+ let (| SeqMap | _ |) g expr =
445+ match expr with
446+ | ValApp g g.seq_ map_ vref ([ ty1; ty2], [ Expr.Lambda ( valParams = [ loopVal]; bodyExpr = body) as mapping; input], _) ->
447+ ValueSome ( ty1, ty2, input, mapping, loopVal, body)
448+ | _ -> ValueNone
449+
450+ /// The representation used for
451+ ///
452+ /// for … in … do f (); …; yield …
453+ [<return : Struct>]
454+ let (| SeqCollectSingle | _ |) g expr =
455+ match expr with
456+ | ValApp g g.seq_ collect_ vref ([ ty1; _; ty2], [ Expr.Lambda ( valParams = [ loopVal]; bodyExpr = SimpleSequential g body) as mapping; input], _) ->
457+ ValueSome ( ty1, ty2, input, mapping, loopVal, body)
458+ | _ -> ValueNone
459+
460+ /// for … in … -> …
461+ /// for … in … do yield …
462+ /// for … in … do f (); …; yield …
463+ [<return : Struct>]
464+ let (| SimpleMapping | _ |) g expr =
465+ match expr with
466+ // for … in … -> …
467+ // for … in … do yield …
468+ | ValApp g g.seq_ delay_ vref (_, [ Expr.Lambda ( bodyExpr = SeqMap g ( ty1, ty2, input, mapping, loopVal, body))], _)
469+
470+ // for … in … do f (); …; yield …
471+ | ValApp g g.seq_ delay_ vref (_, [ Expr.Lambda ( bodyExpr = SeqCollectSingle g ( ty1, ty2, input, mapping, loopVal, body))], _) ->
472+ ValueSome ( ty1, ty2, input, mapping, loopVal, body)
473+
474+ | _ -> ValueNone
475+
476+ let LowerComputedListOrArrayExpr tcVal ( g : TcGlobals ) amap ilTyForTy overallExpr =
403477 // If ListCollector is in FSharp.Core then this optimization kicks in
404478 if g.ListCollector_ tcr.CanDeref then
405479 match overallExpr with
@@ -408,8 +482,17 @@ let LowerComputedListOrArrayExpr tcVal (g: TcGlobals) amap overallExpr =
408482 match overallSeqExpr with
409483 // [start..finish]
410484 // [start..step..finish]
411- | IntegralRange g (_, ( start, step, finish)) when g.langVersion.SupportsFeature LanguageFeature.LowerIntegralRangesToFastLoops ->
412- Some ( List.mkFromIntegralRange tcVal g amap m overallElemTy overallSeqExpr start step finish)
485+ | IntegralRange g ( rangeTy, ( start, step, finish)) when
486+ g.langVersion.SupportsFeature LanguageFeature.LowerIntegralRangesToFastLoops
487+ ->
488+ Some ( List.mkFromIntegralRange tcVal g amap m rangeTy overallElemTy overallSeqExpr start step finish None)
489+
490+ // [for … in start..finish -> …]
491+ // [for … in start..step..finish -> …]
492+ | SimpleMapping g (_, _, rangeExpr & IntegralRange g ( rangeTy, ( start, step, finish)), _, loopVal, body) when
493+ g.langVersion.SupportsFeature LanguageFeature.LowerIntegralRangesToFastLoops
494+ ->
495+ Some ( List.mkFromIntegralRange tcVal g amap m rangeTy overallElemTy rangeExpr start step finish ( Some ( loopVal, body)))
413496
414497 // [(* Anything more complex. *)]
415498 | _ ->
@@ -421,8 +504,17 @@ let LowerComputedListOrArrayExpr tcVal (g: TcGlobals) amap overallExpr =
421504 match overallSeqExpr with
422505 // [|start..finish|]
423506 // [|start..step..finish|]
424- | IntegralRange g (_, ( start, step, finish)) when g.langVersion.SupportsFeature LanguageFeature.LowerIntegralRangesToFastLoops ->
425- Some ( Array.mkFromIntegralRange g m overallElemTy overallSeqExpr start step finish)
507+ | IntegralRange g ( rangeTy, ( start, step, finish)) when
508+ g.langVersion.SupportsFeature LanguageFeature.LowerIntegralRangesToFastLoops
509+ ->
510+ Some ( Array.mkFromIntegralRange g m rangeTy ( ilTyForTy overallElemTy) overallElemTy overallSeqExpr start step finish None)
511+
512+ // [|for … in start..finish -> …|]
513+ // [|for … in start..step..finish -> …|]
514+ | SimpleMapping g (_, _, rangeExpr & IntegralRange g ( rangeTy, ( start, step, finish)), _, loopVal, body) when
515+ g.langVersion.SupportsFeature LanguageFeature.LowerIntegralRangesToFastLoops
516+ ->
517+ Some ( Array.mkFromIntegralRange g m rangeTy ( ilTyForTy overallElemTy) overallElemTy rangeExpr start step finish ( Some ( loopVal, body)))
426518
427519 // [|(* Anything more complex. *)|]
428520 | _ ->
0 commit comments