diff --git a/src/fsharp/creflect.fs b/src/fsharp/creflect.fs index 370b86fa80c..d7b9784f74b 100644 --- a/src/fsharp/creflect.fs +++ b/src/fsharp/creflect.fs @@ -203,8 +203,7 @@ and ConvExpr cenv env (expr : Expr) = and private ConvExprCore cenv (env : QuotationTranslationEnv) (expr: Expr) : QP.ExprData = - // Eliminate integer 'for' loops - let expr = DetectFastIntegerForLoops cenv.g expr + let expr = DetectAndOptimizeForExpression cenv.g OptimizeIntRangesOnly expr // Eliminate subsumption coercions for functions. This must be done post-typechecking because we need // complete inference types. diff --git a/src/fsharp/env.fs b/src/fsharp/env.fs index 940bcf4caab..c084d074b55 100644 --- a/src/fsharp/env.fs +++ b/src/fsharp/env.fs @@ -245,6 +245,7 @@ type public TcGlobals = system_Exception_typ : TType; system_Int32_typ : TType; system_String_typ : TType; + system_String_tcref : TyconRef; system_Type_typ : TType; system_TypedReference_tcref : TyconRef option; system_ArgIterator_tcref : TyconRef option; @@ -482,9 +483,11 @@ type public TcGlobals = dispose_info : IntrinsicValRef; + getstring_info : IntrinsicValRef; + range_op_vref : ValRef; + range_step_op_vref : ValRef; range_int32_op_vref : ValRef; - //range_step_op_vref : ValRef; array_get_vref : ValRef; array2D_get_vref : ValRef; array3D_get_vref : ValRef; @@ -642,6 +645,7 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa let bool_ty = mkNonGenericTy bool_tcr let int_ty = mkNonGenericTy int_tcr + let char_ty = mkNonGenericTy char_tcr let obj_ty = mkNonGenericTy obj_tcr let string_ty = mkNonGenericTy string_tcr let byte_ty = mkNonGenericTy byte_tcr @@ -791,7 +795,7 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa fslib_MFQueryRunExtensionsHighPriority_nleref fslib_MFSeqModule_nleref - fslib_MFListModule_nleref + fslib_MFListModule_nleref fslib_MFArrayModule_nleref fslib_MFArray2DModule_nleref fslib_MFArray3DModule_nleref @@ -893,6 +897,8 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa let dispose_info = makeIntrinsicValRef(fslib_MFIntrinsicFunctions_nleref, "Dispose" ,None ,None ,[vara], ([[varaTy]],unit_ty)) + let getstring_info = makeIntrinsicValRef(fslib_MFIntrinsicFunctions_nleref, "GetString" ,None ,None ,[], ([[string_ty];[int_ty]],char_ty)) + let reference_equality_inner_info = makeIntrinsicValRef(fslib_MFHashCompare_nleref, "PhysicalEqualityIntrinsic" ,None ,None ,[vara], mk_rel_sig varaTy) let bitwise_or_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "op_BitwiseOr" ,None ,None ,[vara], mk_binop_ty varaTy) @@ -917,6 +923,7 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa let typedefof_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "typedefof" ,None ,Some "TypeDefOf",[vara], ([],system_Type_typ)) let enum_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "enum" ,None ,Some "ToEnum" ,[vara], ([[int_ty]],varaTy)) let range_op_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "op_Range" ,None ,None ,[vara], ([[varaTy];[varaTy]],mkSeqTy varaTy)) + let range_step_op_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "op_RangeStep" ,None ,None ,[vara;varb],([[varaTy];[varbTy];[varaTy]],mkSeqTy varaTy)) let range_int32_op_info = makeIntrinsicValRef(fslib_MFOperatorIntrinsics_nleref, "RangeInt32" ,None ,None ,[], ([[int_ty];[int_ty];[int_ty]],mkSeqTy int_ty)) let array2D_get_info = makeIntrinsicValRef(fslib_MFIntrinsicFunctions_nleref, "GetArray2D" ,None ,None ,[vara], ([[mkArrayType 2 varaTy];[int_ty]; [int_ty]],varaTy)) let array3D_get_info = makeIntrinsicValRef(fslib_MFIntrinsicFunctions_nleref, "GetArray3D" ,None ,None ,[vara], ([[mkArrayType 3 varaTy];[int_ty]; [int_ty]; [int_ty]],varaTy)) @@ -941,6 +948,7 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa // Lazy\Value for > 4.0 makeIntrinsicValRef(fslib_MFLazyExtensions_nleref, "Force" ,Some "Lazy`1" ,None ,[vara], ([[mkLazyTy varaTy]; []], varaTy)) let lazy_create_info = makeIntrinsicValRef(fslib_MFLazyExtensions_nleref, "Create" ,Some "Lazy`1" ,None ,[vara], ([[unit_ty --> varaTy]], mkLazyTy varaTy)) + let seq_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "seq" ,None ,Some "CreateSequence" ,[vara], ([[mkSeqTy varaTy]], mkSeqTy varaTy)) let splice_expr_info = makeIntrinsicValRef(fslib_MFExtraTopLevelOperators_nleref, "op_Splice" ,None ,None ,[vara], ([[mkQuotedExprTy varaTy]], varaTy)) let splice_raw_expr_info = makeIntrinsicValRef(fslib_MFExtraTopLevelOperators_nleref, "op_SpliceUntyped" ,None ,None ,[vara], ([[mkRawQuotedExprTy]], varaTy)) @@ -1086,6 +1094,7 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa system_Enum_typ = mkSysNonGenericTy sys "Enum"; system_Exception_typ = mkSysNonGenericTy sys "Exception"; system_String_typ = mkSysNonGenericTy sys "String"; + system_String_tcref = mkSysTyconRef sys "String"; system_Int32_typ = mkSysNonGenericTy sys "Int32"; system_Type_typ = system_Type_typ; system_TypedReference_tcref = if ilg.traits.TypedReferenceTypeScopeRef.IsSome then Some(mkSysTyconRef sys "TypedReference") else None @@ -1358,8 +1367,8 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa enum_vref = ValRefForIntrinsic enum_info; enumOfValue_vref = ValRefForIntrinsic enumOfValue_info; range_op_vref = ValRefForIntrinsic range_op_info; + range_step_op_vref = ValRefForIntrinsic range_step_op_info; range_int32_op_vref = ValRefForIntrinsic range_int32_op_info; - //range_step_op_vref = ValRefForIntrinsic range_step_op_info; array_length_info = array_length_info array_get_vref = ValRefForIntrinsic array_get_info; array2D_get_vref = ValRefForIntrinsic array2D_get_info; @@ -1397,11 +1406,13 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa get_generic_er_equality_comparer_info = get_generic_er_equality_comparer_info; get_generic_per_equality_comparer_info = get_generic_per_equality_comparer_info; dispose_info = dispose_info; + getstring_info = getstring_info; unbox_fast_info = unbox_fast_info; istype_info = istype_info; istype_fast_info = istype_fast_info; lazy_force_info = lazy_force_info; lazy_create_info = lazy_create_info; + create_instance_info = create_instance_info; create_event_info = create_event_info; seq_to_list_info = seq_to_list_info; diff --git a/src/fsharp/opt.fs b/src/fsharp/opt.fs index 3a9460411cf..8728bc2cfca 100644 --- a/src/fsharp/opt.fs +++ b/src/fsharp/opt.fs @@ -1664,9 +1664,6 @@ let TryDetectQueryQuoteAndRun cenv (expr:Expr) = let rec OptimizeExpr cenv (env:IncrementalOptimizationEnv) expr = - // foreach --> fast integer for loops - let expr = DetectFastIntegerForLoops cenv.g expr - // Eliminate subsumption coercions for functions. This must be done post-typechecking because we need // complete inference types. let expr = NormalizeAndAdjustPossibleSubsumptionExprs cenv.g expr @@ -2035,6 +2032,9 @@ and OptimizeLetRec cenv env (binds,bodyExpr,m) = //------------------------------------------------------------------------- and OptimizeLinearExpr cenv env expr contf = + + let expr = DetectAndOptimizeForExpression cenv.g OptimizeAllForExpressions expr + if verboseOptimizations then dprintf "OptimizeLinearExpr\n"; let expr = if cenv.settings.ExpandStructrualValues() then ExpandStructuralBinding cenv expr else expr match expr with diff --git a/src/fsharp/tastops.fs b/src/fsharp/tastops.fs index 360604ae3e7..44d54de8ab6 100644 --- a/src/fsharp/tastops.fs +++ b/src/fsharp/tastops.fs @@ -1427,6 +1427,11 @@ let destArrayTy (g:TcGlobals) ty = | [ty] -> ty | _ -> failwith "destArrayTy"; +let destListTy (g:TcGlobals) ty = + let _,tinst = destAppTy g ty + match tinst with + | [ty] -> ty + | _ -> failwith "destListTy"; let isTypeConstructorEqualToOptional g tcOpt tc = match tcOpt with @@ -1439,6 +1444,8 @@ let isByrefLikeTyconRef g tcref = isTypeConstructorEqualToOptional g g.system_ArgIterator_tcref tcref || isTypeConstructorEqualToOptional g g.system_RuntimeArgumentHandle_tcref tcref +let isStringTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g tcref g.system_String_tcref | _ -> false) +let isListTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g tcref g.list_tcr_canon | _ -> false) let isArrayTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> isArrayTyconRef g tcref | _ -> false) let isArray1DTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g tcref g.il_arr_tcr_map.[0] | _ -> false) let isUnitTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g g.unit_tcr_canon tcref | _ -> false) @@ -5906,6 +5913,8 @@ let mkIsInst ty e m = mkAsmExpr ([ isinst ], [ty],[e], [ ty ], m) let mspec_Object_GetHashCode ilg = IL.mkILNonGenericInstanceMethSpecInTy(ilg.typ_Object,"GetHashCode",[],ilg.typ_int32) let mspec_Type_GetTypeFromHandle ilg = IL.mkILNonGenericStaticMethSpecInTy(ilg.typ_Type,"GetTypeFromHandle",[ilg.typ_RuntimeTypeHandle],ilg.typ_Type) +let mspec_String_Length ilg = mkILNonGenericInstanceMethSpecInTy (ilg.typ_String, "get_Length", [], ilg.typ_int32) + let fspec_Missing_Value ilg = IL.mkILFieldSpecInTy(ilg.typ_Missing.Value, "Value", ilg.typ_Missing.Value) @@ -6052,6 +6061,14 @@ let mkCallQuoteToLinqLambdaExpression g m ty e1 = let mkLazyDelayed g m ty f = mkApps g (typedExprForIntrinsic g m g.lazy_create_info, [[ty]], [ f ], m) let mkLazyForce g m ty e = mkApps g (typedExprForIntrinsic g m g.lazy_force_info, [[ty]], [ e; mkUnit g m ], m) +let mkGetString g m e1 e2 = mkApps g (typedExprForIntrinsic g m g.getstring_info, [], [e1;e2], m) +let mkGetStringChar = mkGetString +let mkGetStringLength g m e = + let mspec = mspec_String_Length g.ilg + /// ILCall(useCallvirt,isProtected,valu,newobj,valUseFlags,isProp,noTailCall,mref,actualTypeInst,actualMethInst, retTy) + Expr.Op(TOp.ILCall(false,false,false,false,ValUseFlag.NormalValUse,true,false,mspec.MethodRef,[],[],[g.int32_ty]),[],[e],m) + + // Quotations can't contain any IL. // As a result, we aim to get rid of all IL generation in the typechecker and pattern match // compiler, or else train the quotation generator to understand the generated IL. @@ -7779,34 +7796,92 @@ let (|RangeInt32Step|_|) g expr = when valRefEq g vf g.range_op_vref && typeEquiv g tyarg g.int_ty -> Some(startExpr, 1, finishExpr) // detect (RangeInt32 startExpr N finishExpr), the inlined/compiled form of 'n .. m' and 'n .. N .. m' - | Expr.App(Expr.Val(vf,_,_),_,[],[startExpr; Int32Expr n; finishExpr],_) + | Expr.App(Expr.Val(vf,_,_),_,[],[startExpr; Int32Expr n; finishExpr],_) when valRefEq g vf g.range_int32_op_vref -> Some(startExpr, n, finishExpr) | _ -> None - -// Detect the compiled or optimized form of a 'for in .. do ' expression over integers -// Detect the compiled or optimized form of a 'for in .. .. do ' expression over integers when step is positive -let (|CompiledInt32ForEachExprWithKnownStep|_|) g expr = - match expr with - | Let (_enumerableVar, RangeInt32Step g (startExpr, step, finishExpr), _, - Let (_enumeratorVar, _getEnumExpr, spBind, - TryFinally (WhileLoopForCompiledForEachExpr (_guardExpr, Let (elemVar,_currentExpr,_,bodyExpr), m), _cleanupExpr))) -> +let (|ExtractTypeOfExpr|_|) g expr = Some (tyOfExpr g expr) - let spForLoop = match spBind with SequencePointAtBinding(spStart) -> SequencePointAtForLoop(spStart) | _ -> NoSequencePointAtForLoop +type OptimizeForExpressionOptions = OptimizeIntRangesOnly | OptimizeAllForExpressions - Some(spForLoop,elemVar,startExpr,step,finishExpr,bodyExpr,m) - | _ -> - None +let DetectAndOptimizeForExpression g option expr = + match expr with + | Let (_, enumerableExpr, _, + Let (_, _, enumeratorBind, + TryFinally (WhileLoopForCompiledForEachExpr (_, Let (elemVar,_,_,bodyExpr), _), _))) -> -let DetectFastIntegerForLoops g expr = - match expr with - | CompiledInt32ForEachExprWithKnownStep g (spForLoop,elemVar,startExpr,step,finishExpr,bodyExpr,m) - // fast for loops only allow steps 1 and -1 steps at the moment - when step = 1 || step = -1 -> + let m = enumerableExpr.Range + let mBody = bodyExpr.Range + + let spForLoop,mForLoop = match enumeratorBind with SequencePointAtBinding(spStart) -> SequencePointAtForLoop(spStart),spStart | _ -> NoSequencePointAtForLoop,m + let spWhileLoop = match enumeratorBind with SequencePointAtBinding(spStart) -> SequencePointAtWhileLoop(spStart)| _ -> NoSequencePointAtWhileLoop + + match option,enumerableExpr with + | _,RangeInt32Step g (startExpr, step, finishExpr) -> + match step with + | -1 | 1 -> mkFastForLoop g (spForLoop,m,elemVar,startExpr,(step = 1),finishExpr,bodyExpr) - | _ -> expr + | _ -> expr + | OptimizeAllForExpressions,ExtractTypeOfExpr g ty when isStringTy g ty -> + // type is string, optimize for expression as: + // let $str = enumerable + // for $idx in 0..(str.Length - 1) do + // let elem = str.[idx] + // body elem + + let strVar ,strExpr = mkCompGenLocal m "str" ty + let idxVar ,idxExpr = mkCompGenLocal m "idx" g.int32_ty + + let lengthExpr = mkGetStringLength g m strExpr + let charExpr = mkGetStringChar g m strExpr idxExpr + + let startExpr = mkZero g m + let finishExpr = mkDecr g mForLoop lengthExpr + let loopItemExpr = mkCoerceIfNeeded g elemVar.Type g.char_ty charExpr // for compat reasons, loop item over string is sometimes object, not char + let bodyExpr = mkCompGenLet mBody elemVar loopItemExpr bodyExpr + let forExpr = mkFastForLoop g (spForLoop,m,idxVar,startExpr,true,finishExpr,bodyExpr) + let expr = mkCompGenLet m strVar enumerableExpr forExpr + expr + | OptimizeAllForExpressions,ExtractTypeOfExpr g ty when isListTy g ty -> + // type is list, optimize for expression as: + // let mutable $currentVar = listExpr + // let mutable $nextVar = $tailOrNull + // while $guardExpr do + // let i = $headExpr + // bodyExpr () + // $current <- $next + // $next <- $tailOrNull + + let IndexHead = 0 + let IndexTail = 1 + + let currentVar ,currentExpr = mkMutableCompGenLocal m "current" ty + let nextVar ,nextExpr = mkMutableCompGenLocal m "next" ty + let elemTy = destListTy g ty + + let guardExpr = mkNonNullTest g m nextExpr + let headOrDefaultExpr = mkUnionCaseFieldGetUnproven(currentExpr,g.cons_ucref,[elemTy],IndexHead,m) + let tailOrNullExpr = mkUnionCaseFieldGetUnproven(currentExpr,g.cons_ucref,[elemTy],IndexTail,mBody) + let bodyExpr = + mkCompGenLet m elemVar headOrDefaultExpr + (mkCompGenSequential mBody + bodyExpr + (mkCompGenSequential mBody + (mkValSet mBody (mkLocalValRef currentVar) nextExpr) + (mkValSet mBody (mkLocalValRef nextVar) tailOrNullExpr) + ) + ) + let whileExpr = mkWhile g (spWhileLoop, WhileLoopForCompiledForEachExprMarker, guardExpr, bodyExpr, m) + + let expr = + mkCompGenLet m currentVar enumerableExpr + (mkCompGenLet m nextVar tailOrNullExpr whileExpr) + + expr + | _ -> expr + | _ -> expr // Used to remove Expr.Link for inner expressions in pattern matches -let (|InnerExprPat|) expr = stripExpr expr \ No newline at end of file +let (|InnerExprPat|) expr = stripExpr expr diff --git a/src/fsharp/tastops.fsi b/src/fsharp/tastops.fsi index 447f9f1fe41..5adeb1bfff5 100644 --- a/src/fsharp/tastops.fsi +++ b/src/fsharp/tastops.fsi @@ -949,10 +949,13 @@ type TypeDefMetadata = val metadataOfTycon : Tycon -> TypeDefMetadata val metadataOfTy : TcGlobals -> TType -> TypeDefMetadata +val isStringTy : TcGlobals -> TType -> bool +val isListTy : TcGlobals -> TType -> bool val isILAppTy : TcGlobals -> TType -> bool val isArrayTy : TcGlobals -> TType -> bool val isArray1DTy : TcGlobals -> TType -> bool val destArrayTy : TcGlobals -> TType -> TType +val destListTy : TcGlobals -> TType -> TType val mkArrayTy : TcGlobals -> int -> TType -> range -> TType val isArrayTyconRef : TcGlobals -> TyconRef -> bool @@ -1373,7 +1376,9 @@ val (|SpecialComparableHeadType|_|) : TcGlobals -> TType -> TType list option val (|SpecialEquatableHeadType|_|) : TcGlobals -> TType -> TType list option val (|SpecialNotEquatableHeadType|_|) : TcGlobals -> TType -> unit option -val DetectFastIntegerForLoops : TcGlobals -> Expr -> Expr +type OptimizeForExpressionOptions = OptimizeIntRangesOnly | OptimizeAllForExpressions +val DetectAndOptimizeForExpression : TcGlobals -> OptimizeForExpressionOptions -> Expr -> Expr + val TryEliminateDesugaredConstants : TcGlobals -> range -> Const -> Expr option val ValIsExplicitImpl : TcGlobals -> Val -> bool diff --git a/tests/fsharp/core/forexpression/build.bat b/tests/fsharp/core/forexpression/build.bat new file mode 100644 index 00000000000..a6ff3718fe7 --- /dev/null +++ b/tests/fsharp/core/forexpression/build.bat @@ -0,0 +1,6 @@ +@if "%_echo%"=="" echo off + +call %~d0%~p0..\..\single-test-build.bat + +exit /b %ERRORLEVEL% + diff --git a/tests/fsharp/core/forexpression/run.bat b/tests/fsharp/core/forexpression/run.bat new file mode 100644 index 00000000000..ceb0a61a545 --- /dev/null +++ b/tests/fsharp/core/forexpression/run.bat @@ -0,0 +1,7 @@ +@if "%_echo%"=="" echo off + +call %~d0%~p0..\..\single-test-run.bat + +exit /b %ERRORLEVEL% + + diff --git a/tests/fsharp/core/forexpression/test.fsx b/tests/fsharp/core/forexpression/test.fsx new file mode 100644 index 00000000000..4abb0fa9e31 --- /dev/null +++ b/tests/fsharp/core/forexpression/test.fsx @@ -0,0 +1,153 @@ +#if Portable +module Core_forexpression +#endif + +let failures = ref false +let report_failure () = + stderr.WriteLine " NO"; failures := true +let test s b = stderr.Write(s:string); if b then stderr.WriteLine " OK" else report_failure() + +#if NetCore +#else +let argv = System.Environment.GetCommandLineArgs() +let SetCulture() = + if argv.Length > 2 && argv.[1] = "--culture" then begin + let cultureString = argv.[2] in + let culture = new System.Globalization.CultureInfo(cultureString) in + stdout.WriteLine ("Running under culture "+culture.ToString()+"..."); + System.Threading.Thread.CurrentThread.CurrentCulture <- culture + end + +do SetCulture() +#endif + +open System +open System.Collections.Generic + +let count = 1000 +let testString = "19740531" +let testData = + [| + for i in 0..count -> [| for inner in 0..i -> inner |] + |] +let expectedArraySum = 167167000 // Find an expression for this sum from count +let expectedRangeSum = ((count + 1) * count) / 2 +let expectedStringSum = 30 + +let getTestData (inner : int [] -> #seq) (outer : #seq [] -> #seq<'U>) = + (testData |> Array.map inner) |> outer + +// sumOverArray covers the case when the sequence type +// is an Array`1 +let sumOverArray () = + let inner xs = xs + let outer xs = xs + let testData : int [] [] = getTestData inner outer + let mutable sum = 0 + for outer in testData do + for inner in outer do + sum <- sum + inner + sum + +// sum over seq covers the case when no optimizations can be +// found and F# has to rely on .GetEnumerator() +let sumOverSeq () = + let inner = Array.toSeq + let outer = Array.toSeq + let testData : seq> = getTestData inner outer + let mutable sum = 0 + for outer in testData do + for inner in outer do + sum <- sum + inner + sum + +// sum over seq covers a regression case when Dictionary +// shouldn'be mistaken for an IList +let sumOverDictionary () = + let inner xs = + let d = Dictionary() + xs |> Array.iteri (fun i x -> d.Add(i,x)) + d + let testData : Dictionary [] = testData |> Array.map inner + let mutable sum = 0 + for outer in testData do + for inner in outer do + sum <- sum + inner.Value + sum + +// sumOverResizeArray covers the case when the sequence type +// extends an IList`1 +let sumOverResizeArray () = + let inner (xs : int []) = ResizeArray<_>(xs) + let outer (xs : #seq>) = ResizeArray<_>(xs) + let testData : ResizeArray> = getTestData inner outer + let mutable sum = 0 + for outer in testData do + for inner in outer do + sum <- sum + inner + sum +// sumOverIList covers the case when the sequence type +// is IList`1 +let sumOverIList () = + let inner (xs : int []) = ResizeArray<_>(xs) :> IList<_> + let outer (xs : #seq>) = ResizeArray<_>(xs) :> IList<_> + let testData : IList> = getTestData inner outer + let mutable sum = 0 + for outer in testData do + for inner in outer do + sum <- sum + inner + sum + +// sumOverList invokes the case when the sequence type +// is a 'T list +let sumOverList () = + let inner = Array.toList + let outer = Array.toList + let testData : int list list = getTestData inner outer + let mutable sum = 0 + for outer in testData do + for inner in outer do + sum <- sum + inner + sum + +// sumOverRange invokes the case when the sequence type is +// of the form n..m +let sumOverRange () = + let mutable sum = 0 + for i in 0..count do + sum <- sum + i + sum + +// sumOverString invokes the case when the sequence type is +// a string +let sumOverString () = + let mutable sum = 0 + for i in testString do +#if Portable + sum <- sum + ((int (i :?> char)) - (int '0')) +#else + sum <- sum + ((int i) - (int '0')) +#endif + sum + +let arraySum = sumOverArray () +let seqSum = sumOverSeq () +let dictionarySum = sumOverDictionary () +let ResizeArraySum = sumOverResizeArray () +let listSum = sumOverList () +let ilistSum = sumOverIList () +let rangeSum = sumOverRange () +let stringSum = sumOverString () + +do test "arraySum" (expectedArraySum = arraySum ) +do test "seqSum" (expectedArraySum = seqSum ) +do test "dictionarySum" (expectedArraySum = dictionarySum ) +do test "ResizeArraySum" (expectedArraySum = ResizeArraySum) +do test "listSum" (expectedArraySum = listSum ) +do test "ilistSum" (expectedArraySum = ilistSum ) +do test "rangeSum" (expectedRangeSum = rangeSum ) +do test "stringSum" (expectedStringSum = stringSum ) + +let aa = + if !failures then stdout.WriteLine "Test Failed"; exit 1 + else stdout.WriteLine "Test Passed"; System.IO.File.WriteAllText("test.ok","ok"); exit 0 diff --git a/tests/fsharp/core/measures/test.fsx b/tests/fsharp/core/measures/test.fsx index 8b5106e13e1..d5728167e1c 100644 --- a/tests/fsharp/core/measures/test.fsx +++ b/tests/fsharp/core/measures/test.fsx @@ -15,12 +15,13 @@ let test s b = if b then () else report_failure(s) #else let argv = System.Environment.GetCommandLineArgs() let SetCulture() = - if argv.Length > 2 && argv.[1] = "--culture" then begin - let cultureString = argv.[2] in - let culture = new System.Globalization.CultureInfo(cultureString) in + if argv.Length > 2 && argv.[1] = "--culture" then + let cultureString = argv.[2] + let culture = new System.Globalization.CultureInfo(cultureString) stdout.WriteLine ("Running under culture "+culture.ToString()+"..."); System.Threading.Thread.CurrentThread.CurrentCulture <- culture - end + else + System.Threading.Thread.CurrentThread.CurrentCulture <- System.Globalization.CultureInfo.InvariantCulture do SetCulture() #endif diff --git a/tests/fsharp/core/netcore/ConsoleApplication1/Program.cs b/tests/fsharp/core/netcore/ConsoleApplication1/Program.cs index e2e869f0e1b..1cb412a0330 100644 --- a/tests/fsharp/core/netcore/ConsoleApplication1/Program.cs +++ b/tests/fsharp/core/netcore/ConsoleApplication1/Program.cs @@ -28,6 +28,7 @@ static int Main(string[] args) Run("Core_controlMailBox", () => { var x = Core_controlMailBox.aa; }); Run("Core_controlStackOverflow", () => { var x = Core_controlStackOverflow.aa; }); Run("Core_csext", () => { var x = Core_csext.aa; }); + Run("Core_forexpression", () => { var x = Core_forexpression.aa; }); Run("Core_innerpoly", () => { var x = Core_innerpoly.aa; }); Run("Core_int32", () => { var x = Core_int32.aa; }); Run("Core_lazy", () => { var x = Core_lazy.aa; }); diff --git a/tests/fsharp/core/netcore/netcorelibrary1/netcoretestinglibrary.fsproj b/tests/fsharp/core/netcore/netcorelibrary1/netcoretestinglibrary.fsproj index 17304f6e603..2fa04bbfa57 100644 --- a/tests/fsharp/core/netcore/netcorelibrary1/netcoretestinglibrary.fsproj +++ b/tests/fsharp/core/netcore/netcorelibrary1/netcoretestinglibrary.fsproj @@ -91,6 +91,9 @@ csext-test.fsx + + forexpression-test.fsx + innerpoly-test.fsx diff --git a/tests/fsharp/core/portable/ConsoleApplication1/Program.cs b/tests/fsharp/core/portable/ConsoleApplication1/Program.cs index e2e869f0e1b..1cb412a0330 100644 --- a/tests/fsharp/core/portable/ConsoleApplication1/Program.cs +++ b/tests/fsharp/core/portable/ConsoleApplication1/Program.cs @@ -28,6 +28,7 @@ static int Main(string[] args) Run("Core_controlMailBox", () => { var x = Core_controlMailBox.aa; }); Run("Core_controlStackOverflow", () => { var x = Core_controlStackOverflow.aa; }); Run("Core_csext", () => { var x = Core_csext.aa; }); + Run("Core_forexpression", () => { var x = Core_forexpression.aa; }); Run("Core_innerpoly", () => { var x = Core_innerpoly.aa; }); Run("Core_int32", () => { var x = Core_int32.aa; }); Run("Core_lazy", () => { var x = Core_lazy.aa; }); diff --git a/tests/fsharp/core/portable/portablelibrary1/portabletestinglibrary.fsproj b/tests/fsharp/core/portable/portablelibrary1/portabletestinglibrary.fsproj index 316c24d237c..36ff96ba4f8 100644 --- a/tests/fsharp/core/portable/portablelibrary1/portabletestinglibrary.fsproj +++ b/tests/fsharp/core/portable/portablelibrary1/portabletestinglibrary.fsproj @@ -57,6 +57,7 @@ controlMailbox-test.fsx controlStackOverflow-test.fsx csext-test.fsx + forexpression-test.fsx innerpoly-test.fsx int32-test.fsx lazy-test.fsx diff --git a/tests/fsharp/core/quotes/test.fsx b/tests/fsharp/core/quotes/test.fsx index 6aeb71c58d6..f4da0d6794a 100644 --- a/tests/fsharp/core/quotes/test.fsx +++ b/tests/fsharp/core/quotes/test.fsx @@ -67,6 +67,24 @@ type S = module TypedTest = begin + // Checks the shape of the quotation to match that of + // foreach implemented in terms of GetEnumerator () + let (|ForEachShape|_|) = function + | Let ( + inputSequence, + inputSequenceBinding, + Let ( + enumerator, + enumeratorBinding, + TryFinally ( + WhileLoop ( + guard, + Let (i, currentExpr, body)), + cleanup) + ) + ) -> Some inputSequence + | _ -> None + let x = <@ 1 @> test "check SByte" ((<@ 1y @> |> (function SByte 1y -> true | _ -> false))) @@ -108,7 +126,11 @@ module TypedTest = begin // In this example, the types of the start and end points are not known at the point the loop // is typechecked. There was a bug (6064) where the transformation to a ForIntegerRangeLoop was only happening // when types were known - test "check ForIntegerRangeLoop" (<@ for i in failwith "" .. failwith "" do printf "hello" @> |> (function ForIntegerRangeLoop(v,_,_,b) -> true | _ -> false)) + test "check ForIntegerRangeLoop" (<@ for i in failwith "" .. failwith "" do printf "hello" @> |> (function ForIntegerRangeLoop(v,_,_,b) -> true | _ -> false)) + // Checks that foreach over non-integer ranges should have the shape of foreach implemented in terms of GetEnumerator + test "check ForEachInSeq" (<@ for i in seq {for x in 0..10 -> x} do printf "hello" @> |> (function ForEachShape(_) -> true | _ -> false)) + test "check ForEachInList" (<@ for i in "123" do printf "hello" @> |> (function ForEachShape(_) -> true | _ -> false)) + test "check ForEachInString" (<@ for i in [1;2;3] do printf "hello" @> |> (function ForEachShape(_) -> true | _ -> false)) // A slight non orthogonality is that all other 'for' loops go to (quite complex) the desugared form test "check Other Loop" (<@ for i in 1 .. 2 .. 10 do printf "hello" @> |> (function Let(v,_,b) -> true | _ -> false)) test "check Other Loop" (<@ for i in 1L .. 10L do printf "hello" @> |> (function Let(v,_,b) -> true | _ -> false)) diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop01.il.netfx4.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop01.il.netfx4.bsl index 9b6550337d7..70f8fc0cda4 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop01.il.netfx4.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/ForLoop01.il.netfx4.bsl @@ -1,5 +1,5 @@ -// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.16774 +// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.33440 // 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:0:0:0 + .ver 4:4:0:9055 } .assembly ForLoop01 { @@ -29,20 +29,20 @@ } .mresource public FSharpSignatureData.ForLoop01 { - // Offset: 0x00000000 Length: 0x00000163 + // Offset: 0x00000000 Length: 0x00000143 } .mresource public FSharpOptimizationData.ForLoop01 { - // Offset: 0x00000168 Length: 0x00000050 + // Offset: 0x00000148 Length: 0x00000050 } .module ForLoop01.exe -// MVID: {4DAC0DD7-1795-791C-A745-0383D70DAC4D} +// MVID: {542DBE1D-1795-791C-A745-03831DBE2D54} .imagebase 0x00400000 .file alignment 0x00000200 .stackreserve 0x00100000 .subsystem 0x0003 // WINDOWS_CUI .corflags 0x00000001 // ILONLY -// Image base: 0x00000000001F0000 +// Image base: 0x02A30000 // =============== CLASS MEMBERS DECLARATION =================== @@ -63,17 +63,15 @@ .method public static void main@() cil managed { .entrypoint - // Code size 116 (0x74) + // Code size 81 (0x51) .maxstack 5 .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_0, - [1] class [mscorlib]System.Collections.Generic.IEnumerator`1 V_1, - [2] class [FSharp.Core]Microsoft.FSharp.Core.Unit V_2, - [3] int32 wi, - [4] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_4, - [5] int32 V_5, - [6] class [mscorlib]System.IDisposable V_6) + [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) .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' - .line 5,5 : 11,21 + .line 5,5 : 11,21 IL_0000: nop IL_0001: ldc.i4.1 IL_0002: ldc.i4.1 @@ -84,67 +82,39 @@ IL_0009: call class [mscorlib]System.Collections.Generic.IEnumerable`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::CreateSequence(class [mscorlib]System.Collections.Generic.IEnumerable`1) IL_000e: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [FSharp.Core]Microsoft.FSharp.Collections.SeqModule::ToList(class [mscorlib]System.Collections.Generic.IEnumerable`1) IL_0013: stloc.0 - .line 5,5 : 1,24 IL_0014: ldloc.0 - IL_0015: unbox.any class [mscorlib]System.Collections.Generic.IEnumerable`1 - IL_001a: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1 class [mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator() - IL_001f: stloc.1 - .try - { - IL_0020: ldloc.1 - IL_0021: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() - IL_0026: brfalse.s IL_0050 - - .line 6,6 : 4,19 - IL_0028: ldloc.1 - IL_0029: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current() - IL_002e: stloc.3 - IL_002f: ldstr "%A" - IL_0034: 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_0039: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) - IL_003e: stloc.s V_4 - IL_0040: ldloc.3 - IL_0041: stloc.s V_5 - IL_0043: ldloc.s V_4 - IL_0045: ldloc.s V_5 - IL_0047: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) - IL_004c: pop - .line 100001,100001 : 0,0 - IL_004d: nop - IL_004e: br.s IL_0020 - - IL_0050: ldnull - IL_0051: stloc.2 - IL_0052: leave.s IL_0071 - - } // end .try - finally - { - IL_0054: ldloc.1 - IL_0055: isinst [mscorlib]System.IDisposable - IL_005a: stloc.s V_6 - IL_005c: ldloc.s V_6 - IL_005e: brfalse.s IL_0062 - - IL_0060: br.s IL_0064 - - IL_0062: br.s IL_006e - - .line 100001,100001 : 0,0 - IL_0064: ldloc.s V_6 - IL_0066: callvirt instance void [mscorlib]System.IDisposable::Dispose() - IL_006b: ldnull - IL_006c: pop - IL_006d: endfinally - .line 100001,100001 : 0,0 - IL_006e: ldnull - IL_006f: pop - IL_0070: endfinally - .line 100001,100001 : 0,0 - } // end handler - IL_0071: ldloc.2 - IL_0072: pop - IL_0073: ret + IL_0015: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_001a: stloc.1 + .line 5,5 : 1,24 '' + IL_001b: ldloc.1 + IL_001c: ldnull + IL_001d: cgt.un + IL_001f: brfalse.s IL_0050 + + .line 5,5 : 11,21 '' + IL_0021: ldloc.0 + IL_0022: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_HeadOrDefault() + IL_0027: stloc.2 + IL_0028: ldstr "%A" + IL_002d: 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_0032: call !!0 [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::PrintFormatLine>(class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0037: stloc.3 + IL_0038: ldloc.2 + IL_0039: stloc.s V_4 + IL_003b: ldloc.3 + IL_003c: ldloc.s V_4 + IL_003e: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0043: pop + IL_0044: ldloc.1 + IL_0045: stloc.0 + IL_0046: ldloc.0 + IL_0047: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_004c: stloc.1 + .line 100001,100001 : 0,0 '' + IL_004d: nop + IL_004e: br.s IL_001b + + IL_0050: ret } // end of method $ForLoop01::main@ } // end of class ''.$ForLoop01 diff --git a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OptionalArguments/TestLib.cs b/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OptionalArguments/TestLib.cs index 9e87bfe99c5..6e677454584 100644 --- a/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OptionalArguments/TestLib.cs +++ b/tests/fsharpqa/Source/Conformance/DeclarationElements/MemberDefinitions/OptionalArguments/TestLib.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; namespace TestLib { public class T { @@ -13,11 +14,11 @@ public int ValueTypeOptArg(int x = 100) { public int? NullableOptArgNullDefault(int? x = null) { return x; } - + public double? NullableOptArgWithDefault(double? x = 5.7) { return x; - } - + } + public string NullOptArg(string x = null) { return x; } @@ -25,14 +26,14 @@ public string NullOptArg(string x = null) { public string NonNullOptArg(string x = "abc") { return x; } - + public List GenericOptArg(List x = null) { return x; } public string ComboOptionals(string required, string a = null, string b = "abc", int c = 100, int? d = 200, double? e = null, List f = null) { - var result = String.Format("[{0}] [{1}] [{2}] [{3}] [{4}] [{5}]", a, b, c, d, e, f); + var result = String.Format(CultureInfo.InvariantCulture, "[{0}] [{1}] [{2}] [{3}] [{4}] [{5}]", a, b, c, d, e, f); return result; - } + } } } \ No newline at end of file diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnList01.fs b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnList01.fs new file mode 100644 index 00000000000..942d99c3234 --- /dev/null +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnList01.fs @@ -0,0 +1,51 @@ +// #Regression #CodeGen #Optimizations #ControlFlow #NoMono #ReqNOMT +// Compiler should turn 'foreach' loops over lists into 'while' loops +module ForEachOnList01 + +// Some variations to make sure optimizer can detect the foreach properly + +let test1(lst: int list) = + let mutable z = 0 + for x in lst do + z <- z + x + +let test2() = + let mutable z = 0 + for x in [1;2;3] do + z <- z + x + +let test3() = + let xs = [1;2;3] + let mutable z = 0 + for x in xs do + z <- z + x + +let test4() = + let mutable z = 0 + let xs = [1;2;3] + for x in xs do + z <- z + x + +let test5() = + let xs = [1;2;3] + for x in xs do + printfn "%A" x + +// more complex enumerable expression +let test6() = + for i in ( + [1;2;3;4] + |> List.map (fun x -> + x + 1) + ) do + printfn "%O" i + +// multiline body +let test7() = + for i in ( + [1;2;3;4] + |> List.map (fun x -> + x + 1) + ) do + let tmp = i + 1 + printfn "%O" tmp \ No newline at end of file diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnList01.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnList01.il.bsl new file mode 100644 index 00000000000..13e69f9c5fa --- /dev/null +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnList01.il.bsl @@ -0,0 +1,516 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.33440 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly extern FSharp.Core +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: + .ver 4:4:0:9055 +} +.assembly ForEachOnList01 +{ + .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 03 00 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.ForEachOnList01 +{ + // Offset: 0x00000000 Length: 0x000002EB +} +.mresource public FSharpOptimizationData.ForEachOnList01 +{ + // Offset: 0x000002F0 Length: 0x000000DB +} +.module ForEachOnList01.dll +// MVID: {54D54537-56DF-F74F-A745-03833745D554} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x014C0000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class public abstract auto ansi sealed ForEachOnList01 + 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 ) + .class auto ansi serializable nested assembly beforefieldinit test6@38 + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + { + .method assembly specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() + IL_0006: ret + } // end of method test6@38::.ctor + + .method public strict virtual instance int32 + Invoke(int32 x) cil managed + { + // Code size 5 (0x5) + .maxstack 8 + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 39,39 : 21,26 '' + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldc.i4.1 + IL_0003: add + IL_0004: ret + } // end of method test6@38::Invoke + + } // end of class test6@38 + + .class auto ansi serializable nested assembly beforefieldinit test7@47 + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + { + .method assembly specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() + IL_0006: ret + } // end of method test7@47::.ctor + + .method public strict virtual instance int32 + Invoke(int32 x) cil managed + { + // Code size 5 (0x5) + .maxstack 8 + .line 48,48 : 21,26 '' + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldc.i4.1 + IL_0003: add + IL_0004: ret + } // end of method test7@47::Invoke + + } // end of class test7@47 + + .method public static void test1(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 lst) cil managed + { + // Code size 42 (0x2a) + .maxstack 4 + .locals init ([0] int32 z, + [1] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_1, + [2] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_2, + [3] int32 x) + .line 8,8 : 6,23 '' + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + .line 9,9 : 15,18 '' + IL_0003: ldarg.0 + IL_0004: stloc.1 + IL_0005: ldloc.1 + IL_0006: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_000b: stloc.2 + .line 9,9 : 6,21 '' + IL_000c: ldloc.2 + IL_000d: ldnull + IL_000e: cgt.un + IL_0010: brfalse.s IL_0029 + + .line 9,9 : 15,18 '' + IL_0012: ldloc.1 + IL_0013: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_HeadOrDefault() + IL_0018: stloc.3 + IL_0019: ldloc.0 + IL_001a: ldloc.3 + IL_001b: add + IL_001c: stloc.0 + IL_001d: ldloc.2 + IL_001e: stloc.1 + IL_001f: ldloc.1 + IL_0020: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_0025: stloc.2 + IL_0026: nop + IL_0027: br.s IL_000c + + IL_0029: ret + } // end of method ForEachOnList01::test1 + + .method public static void test2() cil managed + { + // Code size 64 (0x40) + .maxstack 6 + .locals init ([0] int32 z, + [1] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_1, + [2] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_2, + [3] int32 x) + .line 13,13 : 6,23 '' + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + .line 14,14 : 15,22 '' + IL_0003: ldc.i4.1 + IL_0004: ldc.i4.2 + IL_0005: ldc.i4.3 + IL_0006: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_000b: 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_0010: 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_0015: 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_001a: stloc.1 + IL_001b: ldloc.1 + IL_001c: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_0021: stloc.2 + .line 14,14 : 6,25 '' + IL_0022: ldloc.2 + IL_0023: ldnull + IL_0024: cgt.un + IL_0026: brfalse.s IL_003f + + .line 14,14 : 15,22 '' + IL_0028: ldloc.1 + IL_0029: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_HeadOrDefault() + IL_002e: stloc.3 + IL_002f: ldloc.0 + IL_0030: ldloc.3 + IL_0031: add + IL_0032: stloc.0 + IL_0033: ldloc.2 + IL_0034: stloc.1 + IL_0035: ldloc.1 + IL_0036: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_003b: stloc.2 + IL_003c: nop + IL_003d: br.s IL_0022 + + IL_003f: ret + } // end of method ForEachOnList01::test2 + + .method public static void test3() cil managed + { + // Code size 68 (0x44) + .maxstack 6 + .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 xs, + [1] int32 z, + [2] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_2, + [3] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_3, + [4] int32 x) + .line 18,18 : 6,22 '' + IL_0000: nop + IL_0001: ldc.i4.1 + IL_0002: ldc.i4.2 + IL_0003: ldc.i4.3 + IL_0004: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_0009: 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_000e: 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_0013: 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_0018: stloc.0 + .line 19,19 : 6,23 '' + IL_0019: ldc.i4.0 + IL_001a: stloc.1 + .line 20,20 : 15,17 '' + IL_001b: ldloc.0 + IL_001c: stloc.2 + IL_001d: ldloc.2 + IL_001e: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_0023: stloc.3 + .line 20,20 : 6,20 '' + IL_0024: ldloc.3 + IL_0025: ldnull + IL_0026: cgt.un + IL_0028: brfalse.s IL_0043 + + .line 20,20 : 15,17 '' + IL_002a: ldloc.2 + IL_002b: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_HeadOrDefault() + IL_0030: stloc.s x + IL_0032: ldloc.1 + IL_0033: ldloc.s x + IL_0035: add + IL_0036: stloc.1 + IL_0037: ldloc.3 + IL_0038: stloc.2 + IL_0039: ldloc.2 + IL_003a: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_003f: stloc.3 + IL_0040: nop + IL_0041: br.s IL_0024 + + IL_0043: ret + } // end of method ForEachOnList01::test3 + + .method public static void test4() cil managed + { + // Code size 68 (0x44) + .maxstack 6 + .locals init ([0] int32 z, + [1] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 xs, + [2] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_2, + [3] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_3, + [4] int32 x) + .line 24,24 : 6,23 '' + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + .line 25,25 : 6,22 '' + IL_0003: ldc.i4.1 + IL_0004: ldc.i4.2 + IL_0005: ldc.i4.3 + IL_0006: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_000b: 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_0010: 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_0015: 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_001a: stloc.1 + .line 26,26 : 15,17 '' + IL_001b: ldloc.1 + IL_001c: stloc.2 + IL_001d: ldloc.2 + IL_001e: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_0023: stloc.3 + .line 26,26 : 6,20 '' + IL_0024: ldloc.3 + IL_0025: ldnull + IL_0026: cgt.un + IL_0028: brfalse.s IL_0043 + + .line 26,26 : 15,17 '' + IL_002a: ldloc.2 + IL_002b: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_HeadOrDefault() + IL_0030: stloc.s x + IL_0032: ldloc.0 + IL_0033: ldloc.s x + IL_0035: add + IL_0036: stloc.0 + IL_0037: ldloc.3 + IL_0038: stloc.2 + IL_0039: ldloc.2 + IL_003a: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_003f: stloc.3 + IL_0040: nop + IL_0041: br.s IL_0024 + + IL_0043: ret + } // end of method ForEachOnList01::test4 + + .method public static void test5() cil managed + { + // Code size 91 (0x5b) + .maxstack 6 + .locals init ([0] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 xs, + [1] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_1, + [2] class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_2, + [3] int32 x, + [4] 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_4) + .line 30,30 : 6,22 '' + IL_0000: nop + IL_0001: ldc.i4.1 + IL_0002: ldc.i4.2 + IL_0003: ldc.i4.3 + IL_0004: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_0009: 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_000e: 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_0013: 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_0018: stloc.0 + .line 31,31 : 15,17 '' + IL_0019: ldloc.0 + IL_001a: stloc.1 + IL_001b: ldloc.1 + IL_001c: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_0021: stloc.2 + .line 31,31 : 6,20 '' + IL_0022: ldloc.2 + IL_0023: ldnull + IL_0024: cgt.un + IL_0026: brfalse.s IL_005a + + .line 31,31 : 15,17 '' + IL_0028: ldloc.1 + IL_0029: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_HeadOrDefault() + IL_002e: stloc.3 + IL_002f: ldstr "%A" + IL_0034: 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_0039: stloc.s V_4 + IL_003b: call class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out() + IL_0040: ldloc.s V_4 + IL_0042: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter>(class [mscorlib]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0047: ldloc.3 + IL_0048: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_004d: pop + IL_004e: ldloc.2 + IL_004f: stloc.1 + IL_0050: ldloc.1 + IL_0051: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_0056: stloc.2 + IL_0057: nop + IL_0058: br.s IL_0022 + + IL_005a: ret + } // end of method ForEachOnList01::test5 + + .method public static void test6() cil managed + { + // Code size 103 (0x67) + .maxstack 8 + .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 i, + [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) + .line 37,39 : 17,27 '' + IL_0000: nop + IL_0001: newobj instance void ForEachOnList01/test6@38::.ctor() + IL_0006: ldc.i4.1 + IL_0007: ldc.i4.2 + IL_0008: ldc.i4.3 + IL_0009: ldc.i4.4 + IL_000a: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_000f: 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_0014: 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_0019: 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_001e: 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_0023: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [FSharp.Core]Microsoft.FSharp.Collections.ListModule::Map(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + IL_0028: stloc.0 + IL_0029: ldloc.0 + IL_002a: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_002f: stloc.1 + .line 36,40 : 5,21 '' + IL_0030: ldloc.1 + IL_0031: ldnull + IL_0032: cgt.un + IL_0034: brfalse.s IL_0066 + + .line 37,39 : 17,27 '' + IL_0036: ldloc.0 + IL_0037: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_HeadOrDefault() + IL_003c: stloc.2 + IL_003d: ldstr "%O" + IL_0042: 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_0047: stloc.3 + IL_0048: call class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out() + IL_004d: ldloc.3 + IL_004e: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter>(class [mscorlib]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0053: ldloc.2 + IL_0054: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0059: pop + IL_005a: ldloc.1 + IL_005b: stloc.0 + IL_005c: ldloc.0 + IL_005d: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_0062: stloc.1 + IL_0063: nop + IL_0064: br.s IL_0030 + + IL_0066: ret + } // end of method ForEachOnList01::test6 + + .method public static void test7() cil managed + { + // Code size 109 (0x6d) + .maxstack 8 + .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 i, + [3] int32 tmp, + [4] 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_4) + .line 46,48 : 17,27 '' + IL_0000: nop + IL_0001: newobj instance void ForEachOnList01/test7@47::.ctor() + IL_0006: ldc.i4.1 + IL_0007: ldc.i4.2 + IL_0008: ldc.i4.3 + IL_0009: ldc.i4.4 + IL_000a: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() + IL_000f: 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_0014: 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_0019: 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_001e: 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_0023: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 [FSharp.Core]Microsoft.FSharp.Collections.ListModule::Map(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + IL_0028: stloc.0 + IL_0029: ldloc.0 + IL_002a: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_002f: stloc.1 + .line 45,49 : 5,21 '' + IL_0030: ldloc.1 + IL_0031: ldnull + IL_0032: cgt.un + IL_0034: brfalse.s IL_006c + + .line 46,48 : 17,27 '' + IL_0036: ldloc.0 + IL_0037: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_HeadOrDefault() + IL_003c: stloc.2 + .line 50,50 : 9,24 '' + IL_003d: ldloc.2 + IL_003e: ldc.i4.1 + IL_003f: add + IL_0040: stloc.3 + .line 51,51 : 9,21 '' + IL_0041: ldstr "%O" + IL_0046: 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_004b: stloc.s V_4 + IL_004d: call class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out() + IL_0052: ldloc.s V_4 + IL_0054: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter>(class [mscorlib]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0059: ldloc.3 + IL_005a: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_005f: pop + IL_0060: ldloc.1 + IL_0061: stloc.0 + IL_0062: ldloc.0 + IL_0063: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_0068: stloc.1 + IL_0069: nop + IL_006a: br.s IL_0030 + + IL_006c: ret + } // end of method ForEachOnList01::test7 + +} // end of class ForEachOnList01 + +.class private abstract auto ansi sealed ''.$ForEachOnList01 + extends [mscorlib]System.Object +{ +} // end of class ''.$ForEachOnList01 + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnString01.fs b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnString01.fs new file mode 100644 index 00000000000..04262a04e63 --- /dev/null +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnString01.fs @@ -0,0 +1,67 @@ +// #Regression #CodeGen #Optimizations #ControlFlow #NoMono #ReqNOMT +// Compiler should turn 'foreach' loops over strings into 'for' loops +module ForEachOnString01 + +open System + +let test1(str: string) = + let mutable z = 0 + for x in str do + z <- z + (int x) + +let test2() = + let mutable z = 0 + for x in "123" do + z <- z + (int x) + +let test3() = + let xs = "123" + let mutable z = 0 + for x in xs do + z <- z + (int x) + +let test4() = + let mutable z = 0 + let xs = "123" + for x in xs do + z <- z + (int x) + +let test5() = + let xs = "123" + for x in xs do + printfn "%A" x + +// test6, test7 makes sure the optimization triggers +// for System.String and String as well. +// They are the same type as string but internally string +// is an alias which potentially could make the optimizer +// miss one case or the other +let test6(str: System.String) = + let mutable z = 0 + for x in str do + z <- z + (int x) + +let test7() = + let xs : String = "123" + let mutable z = 0 + for x in xs do + z <- z + (int x) + +// more complex enumerable expression +let test8() = + for i in ( + "1234" + |> String.map (fun x -> + char ((int x) + 1)) + ) do + printfn "%O" i + +// multiline body +let test9() = + for i in ( + "1234" + |> String.map (fun x -> + char ((int x) + 1)) + ) do + let tmp = System.String.Format("{0} foo", i) + printfn "%O" tmp diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnString01.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnString01.il.bsl new file mode 100644 index 00000000000..e576f4a3807 --- /dev/null +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/ForEachOnString01.il.bsl @@ -0,0 +1,586 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.1 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly extern FSharp.Core +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: + .ver 4:4:0:9055 +} +.assembly ForEachOnString01 +{ + .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 ) + + // + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 03 00 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.ForEachOnString01 +{ + // Offset: 0x00000000 Length: 0x0000036E +} +.mresource public FSharpOptimizationData.ForEachOnString01 +{ + // Offset: 0x00000378 Length: 0x000000FF +} +.module ForEachOnString01.dll +// MVID: {547FB1E9-105C-852B-A745-0383E9B17F54} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x029A0000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class public abstract auto ansi sealed ForEachOnString01 + 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 ) + .class auto ansi serializable nested assembly beforefieldinit test8@54 + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + { + .method assembly specialname rtspecialname + instance void .ctor() cil managed + { + // + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() + IL_0006: ret + } // end of method test8@54::.ctor + + .method public strict virtual instance char + Invoke(char x) cil managed + { + // + .maxstack 8 + .language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}' + .line 55,55 : 21,39 'C:\\Users\\latkin\\Source\\Repos\\visualfsharp\\tests\\fsharpqa\\Source\\Optimizations\\ForLoop\\ForEachOnString01.fs' + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: conv.i4 + IL_0003: ldc.i4.1 + IL_0004: add + IL_0005: conv.u2 + IL_0006: ret + } // end of method test8@54::Invoke + + } // end of class test8@54 + + .class auto ansi serializable nested assembly beforefieldinit test9@63 + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + { + .method assembly specialname rtspecialname + instance void .ctor() cil managed + { + // + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() + IL_0006: ret + } // end of method test9@63::.ctor + + .method public strict virtual instance char + Invoke(char x) cil managed + { + // + .maxstack 8 + .line 64,64 : 21,39 '' + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: conv.i4 + IL_0003: ldc.i4.1 + IL_0004: add + IL_0005: conv.u2 + IL_0006: ret + } // end of method test9@63::Invoke + + } // end of class test9@63 + + .method public static void test1(string str) cil managed + { + // + .maxstack 5 + .locals init ([0] int32 z, + [1] int32 V_1, + [2] int32 V_2, + [3] char x) + .line 8,8 : 6,23 '' + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + .line 9,9 : 6,21 '' + IL_0003: ldc.i4.0 + IL_0004: stloc.2 + IL_0005: ldarg.0 + IL_0006: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_000b: ldc.i4.1 + IL_000c: sub + IL_000d: stloc.1 + IL_000e: ldloc.1 + IL_000f: ldloc.2 + IL_0010: blt.s IL_0029 + + .line 10,10 : 10,26 '' + IL_0012: ldarg.0 + IL_0013: ldloc.2 + IL_0014: callvirt instance char [mscorlib]System.String::get_Chars(int32) + IL_0019: stloc.3 + IL_001a: ldloc.0 + IL_001b: ldloc.3 + IL_001c: conv.i4 + IL_001d: add + IL_001e: stloc.0 + IL_001f: ldloc.2 + IL_0020: ldc.i4.1 + IL_0021: add + IL_0022: stloc.2 + .line 9,9 : 6,21 '' + IL_0023: ldloc.2 + IL_0024: ldloc.1 + IL_0025: ldc.i4.1 + IL_0026: add + IL_0027: bne.un.s IL_0012 + + IL_0029: ret + } // end of method ForEachOnString01::test1 + + .method public static void test2() cil managed + { + // + .maxstack 5 + .locals init ([0] int32 z, + [1] int32 V_1, + [2] int32 V_2, + [3] char x) + .line 13,13 : 6,23 '' + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + .line 14,14 : 6,23 '' + IL_0003: ldc.i4.0 + IL_0004: stloc.2 + IL_0005: ldstr "123" + IL_000a: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_000f: ldc.i4.1 + IL_0010: sub + IL_0011: stloc.1 + IL_0012: ldloc.1 + IL_0013: ldloc.2 + IL_0014: blt.s IL_0031 + + .line 15,15 : 10,26 '' + IL_0016: ldstr "123" + IL_001b: ldloc.2 + IL_001c: callvirt instance char [mscorlib]System.String::get_Chars(int32) + IL_0021: stloc.3 + IL_0022: ldloc.0 + IL_0023: ldloc.3 + IL_0024: conv.i4 + IL_0025: add + IL_0026: stloc.0 + IL_0027: ldloc.2 + IL_0028: ldc.i4.1 + IL_0029: add + IL_002a: stloc.2 + .line 14,14 : 6,23 '' + IL_002b: ldloc.2 + IL_002c: ldloc.1 + IL_002d: ldc.i4.1 + IL_002e: add + IL_002f: bne.un.s IL_0016 + + IL_0031: ret + } // end of method ForEachOnString01::test2 + + .method public static void test3() cil managed + { + // + .maxstack 5 + .locals init ([0] int32 z, + [1] int32 V_1, + [2] int32 V_2, + [3] char x) + .line 19,19 : 6,23 '' + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + .line 20,20 : 6,20 '' + IL_0003: ldc.i4.0 + IL_0004: stloc.2 + IL_0005: ldstr "123" + IL_000a: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_000f: ldc.i4.1 + IL_0010: sub + IL_0011: stloc.1 + IL_0012: ldloc.1 + IL_0013: ldloc.2 + IL_0014: blt.s IL_0031 + + .line 21,21 : 10,26 '' + IL_0016: ldstr "123" + IL_001b: ldloc.2 + IL_001c: callvirt instance char [mscorlib]System.String::get_Chars(int32) + IL_0021: stloc.3 + IL_0022: ldloc.0 + IL_0023: ldloc.3 + IL_0024: conv.i4 + IL_0025: add + IL_0026: stloc.0 + IL_0027: ldloc.2 + IL_0028: ldc.i4.1 + IL_0029: add + IL_002a: stloc.2 + .line 20,20 : 6,20 '' + IL_002b: ldloc.2 + IL_002c: ldloc.1 + IL_002d: ldc.i4.1 + IL_002e: add + IL_002f: bne.un.s IL_0016 + + IL_0031: ret + } // end of method ForEachOnString01::test3 + + .method public static void test4() cil managed + { + // + .maxstack 5 + .locals init ([0] int32 z, + [1] int32 V_1, + [2] int32 V_2, + [3] char x) + .line 24,24 : 6,23 '' + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + .line 26,26 : 6,20 '' + IL_0003: ldc.i4.0 + IL_0004: stloc.2 + IL_0005: ldstr "123" + IL_000a: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_000f: ldc.i4.1 + IL_0010: sub + IL_0011: stloc.1 + IL_0012: ldloc.1 + IL_0013: ldloc.2 + IL_0014: blt.s IL_0031 + + .line 27,27 : 10,26 '' + IL_0016: ldstr "123" + IL_001b: ldloc.2 + IL_001c: callvirt instance char [mscorlib]System.String::get_Chars(int32) + IL_0021: stloc.3 + IL_0022: ldloc.0 + IL_0023: ldloc.3 + IL_0024: conv.i4 + IL_0025: add + IL_0026: stloc.0 + IL_0027: ldloc.2 + IL_0028: ldc.i4.1 + IL_0029: add + IL_002a: stloc.2 + .line 26,26 : 6,20 '' + IL_002b: ldloc.2 + IL_002c: ldloc.1 + IL_002d: ldc.i4.1 + IL_002e: add + IL_002f: bne.un.s IL_0016 + + IL_0031: ret + } // end of method ForEachOnString01::test4 + + .method public static void test5() cil managed + { + // + .maxstack 5 + .locals init ([0] int32 V_0, + [1] int32 V_1, + [2] char x, + [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) + .line 31,31 : 6,20 '' + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.1 + IL_0003: ldstr "123" + IL_0008: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_000d: ldc.i4.1 + IL_000e: sub + IL_000f: stloc.0 + IL_0010: ldloc.0 + IL_0011: ldloc.1 + IL_0012: blt.s IL_0047 + + .line 32,32 : 10,24 '' + IL_0014: ldstr "123" + IL_0019: ldloc.1 + IL_001a: callvirt instance char [mscorlib]System.String::get_Chars(int32) + IL_001f: stloc.2 + IL_0020: ldstr "%A" + IL_0025: 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,char>::.ctor(string) + IL_002a: stloc.3 + IL_002b: call class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out() + IL_0030: ldloc.3 + IL_0031: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter>(class [mscorlib]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + 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: ldc.i4.1 + IL_003f: add + IL_0040: stloc.1 + .line 31,31 : 6,20 '' + IL_0041: ldloc.1 + IL_0042: ldloc.0 + IL_0043: ldc.i4.1 + IL_0044: add + IL_0045: bne.un.s IL_0014 + + IL_0047: ret + } // end of method ForEachOnString01::test5 + + .method public static void test6(string str) cil managed + { + // + .maxstack 5 + .locals init ([0] int32 z, + [1] int32 V_1, + [2] int32 V_2, + [3] char x) + .line 40,40 : 6,23 '' + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + .line 41,41 : 6,21 '' + IL_0003: ldc.i4.0 + IL_0004: stloc.2 + IL_0005: ldarg.0 + IL_0006: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_000b: ldc.i4.1 + IL_000c: sub + IL_000d: stloc.1 + IL_000e: ldloc.1 + IL_000f: ldloc.2 + IL_0010: blt.s IL_0029 + + .line 42,42 : 10,26 '' + IL_0012: ldarg.0 + IL_0013: ldloc.2 + IL_0014: callvirt instance char [mscorlib]System.String::get_Chars(int32) + IL_0019: stloc.3 + IL_001a: ldloc.0 + IL_001b: ldloc.3 + IL_001c: conv.i4 + IL_001d: add + IL_001e: stloc.0 + IL_001f: ldloc.2 + IL_0020: ldc.i4.1 + IL_0021: add + IL_0022: stloc.2 + .line 41,41 : 6,21 '' + IL_0023: ldloc.2 + IL_0024: ldloc.1 + IL_0025: ldc.i4.1 + IL_0026: add + IL_0027: bne.un.s IL_0012 + + IL_0029: ret + } // end of method ForEachOnString01::test6 + + .method public static void test7() cil managed + { + // + .maxstack 5 + .locals init ([0] int32 z, + [1] int32 V_1, + [2] int32 V_2, + [3] char x) + .line 46,46 : 6,23 '' + IL_0000: nop + IL_0001: ldc.i4.0 + IL_0002: stloc.0 + .line 47,47 : 6,20 '' + IL_0003: ldc.i4.0 + IL_0004: stloc.2 + IL_0005: ldstr "123" + IL_000a: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_000f: ldc.i4.1 + IL_0010: sub + IL_0011: stloc.1 + IL_0012: ldloc.1 + IL_0013: ldloc.2 + IL_0014: blt.s IL_0031 + + .line 48,48 : 10,26 '' + IL_0016: ldstr "123" + IL_001b: ldloc.2 + IL_001c: callvirt instance char [mscorlib]System.String::get_Chars(int32) + IL_0021: stloc.3 + IL_0022: ldloc.0 + IL_0023: ldloc.3 + IL_0024: conv.i4 + IL_0025: add + IL_0026: stloc.0 + IL_0027: ldloc.2 + IL_0028: ldc.i4.1 + IL_0029: add + IL_002a: stloc.2 + .line 47,47 : 6,20 '' + IL_002b: ldloc.2 + IL_002c: ldloc.1 + IL_002d: ldc.i4.1 + IL_002e: add + IL_002f: bne.un.s IL_0016 + + IL_0031: ret + } // end of method ForEachOnString01::test7 + + .method public static void test8() cil managed + { + // + .maxstack 5 + .locals init ([0] string V_0, + [1] int32 V_1, + [2] int32 V_2, + [3] char i, + [4] 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_4) + .line 53,55 : 17,40 '' + IL_0000: nop + IL_0001: newobj instance void ForEachOnString01/test8@54::.ctor() + IL_0006: ldstr "1234" + IL_000b: call string [FSharp.Core]Microsoft.FSharp.Core.StringModule::Map(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, + string) + IL_0010: stloc.0 + .line 52,56 : 5,21 '' + IL_0011: ldc.i4.0 + IL_0012: stloc.2 + IL_0013: ldloc.0 + IL_0014: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_0019: ldc.i4.1 + IL_001a: sub + IL_001b: stloc.1 + IL_001c: ldloc.1 + IL_001d: ldloc.2 + IL_001e: blt.s IL_0051 + + .line 57,57 : 9,23 '' + IL_0020: ldloc.0 + IL_0021: ldloc.2 + IL_0022: callvirt instance char [mscorlib]System.String::get_Chars(int32) + IL_0027: stloc.3 + IL_0028: ldstr "%O" + IL_002d: 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,char>::.ctor(string) + IL_0032: stloc.s V_4 + IL_0034: call class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out() + IL_0039: ldloc.s V_4 + IL_003b: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter>(class [mscorlib]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0040: ldloc.3 + IL_0041: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0046: pop + IL_0047: ldloc.2 + IL_0048: ldc.i4.1 + IL_0049: add + IL_004a: stloc.2 + .line 52,56 : 5,21 '' + IL_004b: ldloc.2 + IL_004c: ldloc.1 + IL_004d: ldc.i4.1 + IL_004e: add + IL_004f: bne.un.s IL_0020 + + IL_0051: ret + } // end of method ForEachOnString01::test8 + + .method public static void test9() cil managed + { + // + .maxstack 5 + .locals init ([0] string V_0, + [1] int32 V_1, + [2] int32 V_2, + [3] char i, + [4] string tmp, + [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) + .line 62,64 : 17,40 '' + IL_0000: nop + IL_0001: newobj instance void ForEachOnString01/test9@63::.ctor() + IL_0006: ldstr "1234" + IL_000b: call string [FSharp.Core]Microsoft.FSharp.Core.StringModule::Map(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, + string) + IL_0010: stloc.0 + .line 61,65 : 5,21 '' + IL_0011: ldc.i4.0 + IL_0012: stloc.2 + IL_0013: ldloc.0 + IL_0014: callvirt instance int32 [mscorlib]System.String::get_Length() + IL_0019: ldc.i4.1 + IL_001a: sub + IL_001b: stloc.1 + IL_001c: ldloc.1 + IL_001d: ldloc.2 + IL_001e: blt.s IL_0064 + + .line 66,66 : 13,16 '' + IL_0020: ldloc.0 + IL_0021: ldloc.2 + IL_0022: callvirt instance char [mscorlib]System.String::get_Chars(int32) + IL_0027: stloc.3 + .line 66,66 : 9,53 '' + IL_0028: ldstr "{0} foo" + IL_002d: ldloc.3 + IL_002e: box [mscorlib]System.Char + IL_0033: call string [mscorlib]System.String::Format(string, + object) + IL_0038: stloc.s tmp + .line 67,67 : 9,21 '' + IL_003a: ldstr "%O" + IL_003f: 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,string>::.ctor(string) + IL_0044: stloc.s V_5 + IL_0046: call class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out() + IL_004b: ldloc.s V_5 + IL_004d: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter>(class [mscorlib]System.IO.TextWriter, + class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4) + IL_0052: ldloc.s tmp + IL_0054: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0059: pop + IL_005a: ldloc.2 + IL_005b: ldc.i4.1 + IL_005c: add + IL_005d: stloc.2 + .line 61,65 : 5,21 '' + IL_005e: ldloc.2 + IL_005f: ldloc.1 + IL_0060: ldc.i4.1 + IL_0061: add + IL_0062: bne.un.s IL_0020 + + IL_0064: ret + } // end of method ForEachOnString01::test9 + +} // end of class ForEachOnString01 + +.class private abstract auto ansi sealed ''.$ForEachOnString01 + extends [mscorlib]System.Object +{ +} // end of class ''.$ForEachOnString01 + + +// ============================================================= + +// diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable03.il.bsl b/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable03.il.bsl index 367749302d1..f95a853d16d 100644 --- a/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable03.il.bsl +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/NoIEnumerable03.il.bsl @@ -19,10 +19,10 @@ { .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 ) + 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 03 00 00 00 00 00 ) + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 03 00 00 00 00 00 ) .hash algorithm 0x00008004 .ver 0:0:0:0 @@ -50,18 +50,18 @@ .class public abstract auto ansi sealed M 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 ) + .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 loop3(int32 a, int32 N) cil managed { - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) // Code size 43 (0x2b) .maxstack 5 .locals init ([0] int32 V_0, [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 + .line 7,7 : 4,22 IL_0000: nop IL_0001: ldarg.0 IL_0002: stloc.1 @@ -71,7 +71,7 @@ IL_0006: ldloc.1 IL_0007: blt.s IL_002a - .line 8,8 : 7,20 + .line 8,8 : 7,20 IL_0009: ldstr "aaa" IL_000e: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5::.ctor(string) IL_0013: stloc.2 @@ -84,7 +84,7 @@ IL_0021: ldc.i4.1 IL_0022: add IL_0023: stloc.1 - .line 7,7 : 13,19 + .line 7,7 : 18,19 IL_0024: ldloc.1 IL_0025: ldloc.0 IL_0026: ldc.i4.1 diff --git a/tests/fsharpqa/Source/Optimizations/ForLoop/env.lst b/tests/fsharpqa/Source/Optimizations/ForLoop/env.lst index e0b1f32e8f3..3be9c8230c6 100644 --- a/tests/fsharpqa/Source/Optimizations/ForLoop/env.lst +++ b/tests/fsharpqa/Source/Optimizations/ForLoop/env.lst @@ -1,6 +1,8 @@ # Exclude the genuine CodeGen tests when doing MT runs NOMONO,NoMT SOURCE=NoAllocationOfTuple01.fs ISCFLAGS="-a -g --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd NoAllocationOfTuple01.dll" # NoAllocationOfTuple01.fs NOMONO,NoMT SOURCE=ForEachOnArray01.fs ISCFLAGS="-a -g --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd ForEachOnArray01.dll" # ForEachOnArray01.fs +NOMONO,NoMT SOURCE=ForEachOnList01.fs ISCFLAGS="-a -g --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd ForEachOnList01.dll" # ForEachOnList01.fs +NOMONO,NoMT SOURCE=ForEachOnString01.fs ISCFLAGS="-a -g --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd ForEachOnString01.dll" # ForEachOnString01.fs NOMONO,NoMT SOURCE=ZeroToArrLength01.fs ISCFLAGS="-a -g --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd ZeroToArrLength01.dll" # ZeroToArrLength01.fs NOMONO,NoMT SOURCE=ZeroToArrLength02.fs ISCFLAGS="-a -g --optimize+" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd ZeroToArrLength02.dll" # ZeroToArrLength02.fs diff --git a/tests/test.lst b/tests/test.lst index d0f7e5e841b..71e43a4ed1a 100644 --- a/tests/test.lst +++ b/tests/test.lst @@ -23,6 +23,7 @@ Core02 fsharp\core\csext Core02 ..\testsprivate\fsharp\core\csfromfs Core02 fsharp\core\events Core02 fsharp\core\forwarders +Core02 fsharp\core\forexpression Core02 fsharp\core\fsfromcs Core02 fsharp\core\fsfromfsviacs Core02 fsharp\core\fsiAndModifiers