未验证 提交 166ec385 编写于 作者: D Don Syme 提交者: GitHub

process more large expressions more systematically (#6294)

* process large expressions systematically

* add test cases

* update tests

* Make .NET Desktop fsi.exe 32-bit again and make Desktop fsiAnyCpu.exe (64-bit) the default to launch in VS #6223

* make fsc.exe 32-bit for compat

* make fsc.exe 32-bit for compat

* fix build

* fix build

* ramp up max testing

* correct optimization of linear matches

* improve diagnostics

* fix tests

* tests only on .NET Framework for now

* fix determinism
上级 09a98700
......@@ -256,14 +256,16 @@ module GlobalUsageAnalysis =
let foldLocalVal f z (vref: ValRef) =
if valRefInThisAssembly g.compilingFslib vref then f z vref.Deref
else z
let exprUsageIntercept exprF z expr =
let exprUsageIntercept exprF noInterceptF z origExpr =
let rec recognise context expr =
match expr with
| Expr.Val (v, _, _) ->
match expr with
| Expr.Val (v, _, _) ->
// YES: count free occurrence
let z = foldLocalVal (fun z v -> logUse v (context, [], []) z) z v
Some z
| TyappAndApp(f, _, tys, args, _) ->
foldLocalVal (fun z v -> logUse v (context, [], []) z) z v
| TyappAndApp(f, _, tys, args, _) ->
match f with
| Expr.Val (fOrig, _, _) ->
// app where function is val
......@@ -271,27 +273,27 @@ module GlobalUsageAnalysis =
// collect from args (have intercepted this node)
let collect z f = logUse f (context, tys, args) z
let z = foldLocalVal collect z fOrig
let z = List.fold exprF z args
Some z
List.fold exprF z args
| _ ->
// NO: app but function is not val
None
noInterceptF z origExpr
| Expr.Op(TOp.TupleFieldGet (tupInfo, n), ts, [x], _) when not (evalTupInfoIsStruct tupInfo) ->
let context = TupleGet (n, ts) :: context
recognise context x
// lambdas end top-level status
| Expr.Lambda(_id, _ctorThisValOpt, _baseValOpt, _vs, body, _, _) ->
let z = foldUnderLambda exprF z body
Some z
foldUnderLambda exprF z body
| Expr.TyLambda(_id, _tps, body, _, _) ->
let z = foldUnderLambda exprF z body
Some z
foldUnderLambda exprF z body
| _ ->
None // NO: no intercept
noInterceptF z origExpr
let context = []
recognise context expr
recognise context origExpr
let targetIntercept exprF z = function TTarget(_argvs, body, _) -> Some (foldUnderLambda exprF z body)
let tmethodIntercept exprF z = function TObjExprMethod(_, _, _, _, e, _m) -> Some (foldUnderLambda exprF z e)
......
......@@ -38,46 +38,65 @@ let rec accExpr (cenv:cenv) (env:env) expr =
| Expr.Sequential (e1,e2,_,_,_) ->
accExpr cenv env e1
accExpr cenv env e2
| Expr.Let (bind,body,_,_) ->
accBind cenv env bind
accExpr cenv env body
| Expr.Const (_,_,ty) ->
accTy cenv env ty
| Expr.Val (_v,_vFlags,_m) -> ()
| Expr.Quote(ast,_,_,_m,ty) ->
accExpr cenv env ast
accTy cenv env ty
| Expr.Obj (_,ty,basev,basecall,overrides,iimpls,_m) ->
accTy cenv env ty
accExpr cenv env basecall
accMethods cenv env basev overrides
accIntfImpls cenv env basev iimpls
| LinearOpExpr (_op, tyargs, argsHead, argLast, _m) ->
// Note, LinearOpExpr doesn't include any of the "special" cases for accOp
accTypeInst cenv env tyargs
accExprs cenv env argsHead
// tailcall
accExpr cenv env argLast
| Expr.Op (c,tyargs,args,m) ->
accOp cenv env (c,tyargs,args,m)
| Expr.App(f,fty,tyargs,argsl,_m) ->
accTy cenv env fty
accTypeInst cenv env tyargs
accExpr cenv env f
accExprs cenv env argsl
| Expr.Lambda(_,_ctorThisValOpt,_baseValOpt,argvs,_body,m,rty) ->
let topValInfo = ValReprInfo ([],[argvs |> List.map (fun _ -> ValReprInfo.unnamedTopArg1)],ValReprInfo.unnamedRetVal)
let ty = mkMultiLambdaTy m argvs rty
accLambdas cenv env topValInfo expr ty
| Expr.TyLambda(_,tps,_body,_m,rty) ->
let topValInfo = ValReprInfo (ValReprInfo.InferTyparInfo tps,[],ValReprInfo.unnamedRetVal)
accTy cenv env rty
let ty = mkForallTyIfNeeded tps rty
accLambdas cenv env topValInfo expr ty
| Expr.TyChoose(_tps,e1,_m) ->
accExpr cenv env e1
| Expr.Match(_,_exprm,dtree,targets,m,ty) ->
accTy cenv env ty
accDTree cenv env dtree
accTargets cenv env m ty targets
| Expr.LetRec (binds,e,_m,_) ->
accBinds cenv env binds
accExpr cenv env e
| Expr.StaticOptimization (constraints,e2,e3,_m) ->
accExpr cenv env e2
accExpr cenv env e3
......@@ -87,14 +106,19 @@ let rec accExpr (cenv:cenv) (env:env) expr =
accTy cenv env ty2
| TTyconIsStruct(ty1) ->
accTy cenv env ty1)
| Expr.Link _eref -> failwith "Unexpected reclink"
and accMethods cenv env baseValOpt l = List.iter (accMethod cenv env baseValOpt) l
and accMethods cenv env baseValOpt l =
List.iter (accMethod cenv env baseValOpt) l
and accMethod cenv env _baseValOpt (TObjExprMethod(_slotsig,_attribs,_tps,vs,e,_m)) =
vs |> List.iterSquared (accVal cenv env)
accExpr cenv env e
and accIntfImpls cenv env baseValOpt l = List.iter (accIntfImpl cenv env baseValOpt) l
and accIntfImpls cenv env baseValOpt l =
List.iter (accIntfImpl cenv env baseValOpt) l
and accIntfImpl cenv env baseValOpt (ty,overrides) =
accTy cenv env ty
accMethods cenv env baseValOpt overrides
......@@ -132,11 +156,14 @@ and accLambdas cenv env topValInfo e ety =
| _ ->
accExpr cenv env e
and accExprs cenv env exprs = exprs |> List.iter (accExpr cenv env)
and accExprs cenv env exprs =
exprs |> List.iter (accExpr cenv env)
and accTargets cenv env m ty targets = Array.iter (accTarget cenv env m ty) targets
and accTargets cenv env m ty targets =
Array.iter (accTarget cenv env m ty) targets
and accTarget cenv env _m _ty (TTarget(_vs,e,_)) = accExpr cenv env e
and accTarget cenv env _m _ty (TTarget(_vs,e,_)) =
accExpr cenv env e
and accDTree cenv env x =
match x with
......@@ -169,7 +196,8 @@ and accAttrib cenv env (Attrib(_,_k,args,props,_,_,_m)) =
accExpr cenv env expr2
accTy cenv env ty)
and accAttribs cenv env attribs = List.iter (accAttrib cenv env) attribs
and accAttribs cenv env attribs =
List.iter (accAttrib cenv env) attribs
and accValReprInfo cenv env (ValReprInfo(_,args,ret)) =
args |> List.iterSquared (accArgReprInfo cenv env)
......@@ -188,7 +216,8 @@ and accBind cenv env (bind:Binding) =
let topValInfo = match bind.Var.ValReprInfo with Some info -> info | _ -> ValReprInfo.emptyValData
accLambdas cenv env topValInfo bind.Expr bind.Var.Type
and accBinds cenv env xs = xs |> List.iter (accBind cenv env)
and accBinds cenv env xs =
xs |> List.iter (accBind cenv env)
let accTyconRecdField cenv env _tycon (rfield:RecdField) =
accAttribs cenv env rfield.PropertyAttribs
......@@ -203,13 +232,15 @@ let accTycon cenv env (tycon:Tycon) =
accAttribs cenv env uc.Attribs
uc.RecdFieldsArray |> Array.iter (accTyconRecdField cenv env tycon))
let accTycons cenv env tycons = List.iter (accTycon cenv env) tycons
let accTycons cenv env tycons =
List.iter (accTycon cenv env) tycons
let rec accModuleOrNamespaceExpr cenv env x =
match x with
| ModuleOrNamespaceExprWithSig(_mty, def, _m) -> accModuleOrNamespaceDef cenv env def
and accModuleOrNamespaceDefs cenv env x = List.iter (accModuleOrNamespaceDef cenv env) x
and accModuleOrNamespaceDefs cenv env x =
List.iter (accModuleOrNamespaceDef cenv env) x
and accModuleOrNamespaceDef cenv env x =
match x with
......@@ -221,12 +252,16 @@ and accModuleOrNamespaceDef cenv env x =
| TMAbstract(def) -> accModuleOrNamespaceExpr cenv env def
| TMDefs(defs) -> accModuleOrNamespaceDefs cenv env defs
and accModuleOrNamespaceBinds cenv env xs = List.iter (accModuleOrNamespaceBind cenv env) xs
and accModuleOrNamespaceBinds cenv env xs =
List.iter (accModuleOrNamespaceBind cenv env) xs
and accModuleOrNamespaceBind cenv env x =
match x with
| ModuleOrNamespaceBinding.Binding bind -> accBind cenv env bind
| ModuleOrNamespaceBinding.Module(mspec, rhs) -> accTycon cenv env mspec; accModuleOrNamespaceDef cenv env rhs
| ModuleOrNamespaceBinding.Binding bind ->
accBind cenv env bind
| ModuleOrNamespaceBinding.Module(mspec, rhs) ->
accTycon cenv env mspec
accModuleOrNamespaceDef cenv env rhs
let UnsolvedTyparsOfModuleDef g amap denv (mdef, extraAttribs) =
let cenv =
......
......@@ -141,6 +141,8 @@ type IlxGenIntraAssemblyInfo =
/// that come from both the signature and the implementation.
StaticFieldInfo : Dictionary<ILMethodRef, ILFieldSpec> }
type FakeUnit = | Fake
//--------------------------------------------------------------------------
/// Indicates how the generated IL code is ultimately emitted
......@@ -2044,6 +2046,13 @@ let rec GenExpr (cenv:cenv) (cgbuf:CodeGenBuffer) eenv sp expr sequel =
GenApp cenv cgbuf eenv (f,fty,tyargs,args,m) sequel
| Expr.Val(v,_,m) ->
GenGetVal cenv cgbuf eenv (v,m) sequel
// Most generation of linear expressions is implemented routinely using tailcalls and the correct sequels.
// This is because the element of expansion happens to be the final thing generated in most cases. However
// for large lists we have to process the linearity separately
| LinearOpExpr _ ->
GenLinearExpr cenv cgbuf eenv expr sequel id |> ignore<FakeUnit>
| Expr.Op(op,tyargs,args,m) ->
match op,args,tyargs with
| TOp.ExnConstr(c),_,_ ->
......@@ -2346,12 +2355,27 @@ and GenAllocExn cenv cgbuf eenv (c,args,m) sequel =
(mkNormalNewobj mspec)
GenSequel cenv eenv.cloc cgbuf sequel
and GenAllocUnionCaseCore cenv cgbuf eenv (c,tyargs,n,m) =
let cuspec,idx = GenUnionCaseSpec cenv.amap m eenv.tyenv c tyargs
CG.EmitInstrs cgbuf (pop n) (Push [cuspec.DeclaringType]) (EraseUnions.mkNewData cenv.g.ilg (cuspec, idx))
and GenAllocUnionCase cenv cgbuf eenv (c,tyargs,args,m) sequel =
GenExprs cenv cgbuf eenv args
let cuspec,idx = GenUnionCaseSpec cenv.amap m eenv.tyenv c tyargs
CG.EmitInstrs cgbuf (pop args.Length) (Push [cuspec.DeclaringType]) (EraseUnions.mkNewData cenv.g.ilg (cuspec, idx))
GenAllocUnionCaseCore cenv cgbuf eenv (c,tyargs,args.Length,m)
GenSequel cenv eenv.cloc cgbuf sequel
and GenLinearExpr cenv cgbuf eenv expr sequel (contf: FakeUnit -> FakeUnit) =
match expr with
| LinearOpExpr (TOp.UnionCase c, tyargs, argsFront, argLast, m) ->
GenExprs cenv cgbuf eenv argsFront
GenLinearExpr cenv cgbuf eenv argLast Continue (contf << (fun (Fake) ->
GenAllocUnionCaseCore cenv cgbuf eenv (c, tyargs, argsFront.Length + 1, m)
GenSequel cenv eenv.cloc cgbuf sequel
Fake))
| _ ->
GenExpr cenv cgbuf eenv SPSuppress expr sequel
contf Fake
and GenAllocRecd cenv cgbuf eenv ctorInfo (tcref,argtys,args,m) sequel =
let ty = GenNamedTyApp cenv.amap m eenv.tyenv tcref argtys
......
......@@ -480,9 +480,10 @@ module Pass2_DetermineReqdItems =
/// "val v" - free occurrence
/// "app (f,tps,args)" - occurrence
///
/// On intercepted nodes, must exprF fold to collect from subexpressions.
let ExprEnvIntercept (tlrS,arityM) exprF z expr =
let accInstance z (fvref:ValRef,tps,args) (* f known local *) =
/// On intercepted nodes, must recurseF fold to collect from subexpressions.
let ExprEnvIntercept (tlrS,arityM) recurseF noInterceptF z expr =
let accInstance z (fvref:ValRef,tps,args) =
let f = fvref.Deref
match Zmap.tryFind f arityM with
......@@ -508,48 +509,51 @@ module Pass2_DetermineReqdItems =
let fclass = BindingGroupSharingSameReqdItems tlrBs
// what determines env?
let frees = FreeInBindings tlrBs
let reqdTypars0 = frees.FreeTyvars.FreeTypars |> Zset.elements (* put in env *)
// put in env
let reqdTypars0 = frees.FreeTyvars.FreeTypars |> Zset.elements
// occurrences contribute to env
let reqdVals0 = frees.FreeLocals |> Zset.elements
// tlrBs are not reqdVals0 for themselves
let reqdVals0 = reqdVals0 |> List.filter (fun gv -> not (fclass.Contains gv))
let reqdVals0 = reqdVals0 |> Zset.ofList valOrder
// collect into env over bodies
let z = PushFrame fclass (reqdTypars0,reqdVals0,m) z
let z = (z,tlrBs) ||> List.fold (foldOn (fun b -> b.Expr) exprF)
let z = SaveFrame fclass z
(* for bindings not marked TRL, collect *)
let z = (z,nonTlrBs) ||> List.fold (foldOn (fun b -> b.Expr) exprF)
let z = PushFrame fclass (reqdTypars0,reqdVals0,m) z
let z = (z,tlrBs) ||> List.fold (foldOn (fun b -> b.Expr) recurseF)
let z = SaveFrame fclass z
// for bindings not marked TRL, collect
let z = (z,nonTlrBs) ||> List.fold (foldOn (fun b -> b.Expr) recurseF)
z
match expr with
| Expr.Val (v,_,_) ->
let z = accInstance z (v,[],[])
Some z
accInstance z (v,[],[])
| Expr.Op (TOp.LValueOp (_,v),_tys,args,_) ->
let z = accInstance z (v,[],[])
let z = List.fold exprF z args
Some z
List.fold recurseF z args
| Expr.App (f,fty,tys,args,m) ->
let f,_fty,tys,args,_m = destApp (f,fty,tys,args,m)
match f with
| Expr.Val (f,_,_) ->
// // YES: APP vspec tps args - log
// YES: APP vspec tps args - log
let z = accInstance z (f,tys,args)
let z = List.fold exprF z args
Some z
List.fold recurseF z args
| _ ->
(* NO: app, but function is not val - no log *)
None
| Expr.LetRec (binds,body,m,_) ->
// NO: app, but function is not val - no log
noInterceptF z expr
| Expr.LetRec (binds, body, m, _) ->
let z = accBinds m z binds
let z = exprF z body
Some z
| Expr.Let (bind,body,m,_) ->
recurseF z body
| Expr.Let (bind,body,m,_) ->
let z = accBinds m z [bind]
let z = exprF z body
Some z
| _ -> None (* NO: no intercept *)
// tailcall for linear sequences
recurseF z body
| _ ->
noInterceptF z expr
/// Initially, reqdTypars(fclass) = freetps(bodies).
......@@ -1073,9 +1077,14 @@ module Pass4_RewriteAssembly =
/// At free vals, fixup 0-call if it is an arity-met constant.
/// Other cases rewrite structurally.
let rec TransExpr (penv: RewriteContext) (z:RewriteState) expr : Expr * RewriteState =
match expr with
// Use TransLinearExpr with a rebuild-continuation for some forms to avoid stack overflows on large terms *)
| Expr.LetRec _ | Expr.Let _ | Expr.Sequential _ ->
// Use TransLinearExpr with a rebuild-continuation for some forms to avoid stack overflows on large terms
| LinearOpExpr _
| LinearMatchExpr _
| Expr.LetRec _ // note, Expr.LetRec not normally considered linear, but keeping it here as it's always been here
| Expr.Let _
| Expr.Sequential _ ->
TransLinearExpr penv z expr (fun res -> res)
// app - call sites may require z.
......@@ -1138,19 +1147,25 @@ module Pass4_RewriteAssembly =
MakePreDecs m pds (mkAndSimplifyMatch spBind exprm m ty dtree targets),z
// all others - below - rewrite structurally - so boiler plate code after this point...
| Expr.Const _ -> expr,z (* constant wrt Val *)
| Expr.Const _ ->
expr,z
| Expr.Quote (a,{contents=Some(typeDefs,argTypes,argExprs,data)},isFromQueryExpression,m,ty) ->
let argExprs,z = List.mapFold (TransExpr penv) z argExprs
Expr.Quote(a,{contents=Some(typeDefs,argTypes,argExprs,data)},isFromQueryExpression,m,ty),z
| Expr.Quote (a,{contents=None},isFromQueryExpression,m,ty) ->
Expr.Quote(a,{contents=None},isFromQueryExpression,m,ty),z
| Expr.Op (c,tyargs,args,m) ->
let args,z = List.mapFold (TransExpr penv) z args
Expr.Op(c,tyargs,args,m),z
| Expr.StaticOptimization (constraints,e2,e3,m) ->
let e2,z = TransExpr penv z e2
let e3,z = TransExpr penv z e3
Expr.StaticOptimization(constraints,e2,e3,m),z
| Expr.TyChoose (_,_,m) ->
error(Error(FSComp.SR.tlrUnexpectedTExpr(),m))
......@@ -1203,9 +1218,16 @@ module Pass4_RewriteAssembly =
let tg1,z = TransDecisionTreeTarget penv z tg1
// tailcall
TransLinearExpr penv z e2 (contf << (fun (e2,z) ->
rebuildLinearMatchExpr (spBind,exprm,dtree,tg1,e2,sp2,m2,ty),z))
rebuildLinearMatchExpr (spBind,exprm,dtree,tg1,e2,sp2,m2,ty), z))
| LinearOpExpr (op, tyargs, argsHead, argLast, m) ->
let argsHead,z = List.mapFold (TransExpr penv) z argsHead
// tailcall
TransLinearExpr penv z argLast (contf << (fun (argLast, z) ->
rebuildLinearOpExpr (op, tyargs, argsHead, argLast, m), z))
| _ ->
// not a linear expression
contf (TransExpr penv z expr)
and TransMethod penv (z:RewriteState) (TObjExprMethod(slotsig,attribs,tps,vs,e,m)) =
......
......@@ -293,25 +293,37 @@ type OptimizationSettings =
}
member x.jitOpt() = match x.jitOptUser with Some f -> f | None -> jitOptDefault
member x.localOpt () = match x.localOptUser with Some f -> f | None -> localOptDefault
member x.crossModuleOpt () = x.localOpt () && (match x.crossModuleOptUser with Some f -> f | None -> crossModuleOptDefault)
member x.KeepOptimizationValues() = x.crossModuleOpt ()
/// inline calls *
member x.InlineLambdas () = x.localOpt ()
/// eliminate unused bindings with no effect
member x.EliminateUnusedBindings () = x.localOpt ()
/// eliminate try around expr with no effect
member x.EliminateTryCatchAndTryFinally () = false // deemed too risky, given tiny overhead of including try/catch. See https://github.com/Microsoft/visualfsharp/pull/376
/// eliminate first part of seq if no effect
member x.EliminateSequential () = x.localOpt ()
/// determine branches in pattern matching
member x.EliminateSwitch () = x.localOpt ()
member x.EliminateRecdFieldGet () = x.localOpt ()
member x.EliminateTupleFieldGet () = x.localOpt ()
member x.EliminatUnionCaseFieldGet () = x.localOpt ()
/// eliminate non-compiler generated immediate bindings
member x.EliminateImmediatelyConsumedLocals() = x.localOpt ()
/// expand "let x = (exp1, exp2, ...)" bind fields as prior tmps
member x.ExpandStructrualValues() = x.localOpt ()
......@@ -1274,9 +1286,13 @@ let rec ExprHasEffect g expr =
| Expr.Let(bind, body, _, _) -> BindingHasEffect g bind || ExprHasEffect g body
// REVIEW: could add Expr.Obj on an interface type - these are similar to records of lambda expressions
| _ -> true
and ExprsHaveEffect g exprs = List.exists (ExprHasEffect g) exprs
and BindingsHaveEffect g binds = List.exists (BindingHasEffect g) binds
and BindingHasEffect g bind = bind.Expr |> ExprHasEffect g
and OpHasEffect g m op =
match op with
| TOp.Tuple _ -> false
......@@ -1788,10 +1804,18 @@ let rec OptimizeExpr cenv (env:IncrementalOptimizationEnv) expr =
match expr with
// treat the common linear cases to avoid stack overflows, using an explicit continuation
| Expr.Sequential _ | Expr.Let _ -> OptimizeLinearExpr cenv env expr (fun x -> x)
| LinearOpExpr _
| LinearMatchExpr _
| Expr.Sequential _
| Expr.Let _ ->
OptimizeLinearExpr cenv env expr (fun x -> x)
| Expr.Const (c, m, ty) ->
OptimizeConst cenv env expr (c, m, ty)
| Expr.Val (v, _vFlags, m) ->
OptimizeVal cenv env expr (v, m)
| Expr.Const (c, m, ty) -> OptimizeConst cenv env expr (c, m, ty)
| Expr.Val (v, _vFlags, m) -> OptimizeVal cenv env expr (v, m)
| Expr.Quote(ast, splices, isFromQueryExpression, m, ty) ->
let splices = ref (splices.Value |> Option.map (map3Of4 (List.map (OptimizeExpr cenv env >> fst))))
Expr.Quote(ast, splices, isFromQueryExpression, m, ty),
......@@ -1800,34 +1824,48 @@ let rec OptimizeExpr cenv (env:IncrementalOptimizationEnv) expr =
HasEffect = false
MightMakeCriticalTailcall=false
Info=UnknownValue }
| Expr.Obj (_, ty, basev, expr, overrides, iimpls, m) -> OptimizeObjectExpr cenv env (ty, basev, expr, overrides, iimpls, m)
| Expr.Op (c, tyargs, args, m) -> OptimizeExprOp cenv env (c, tyargs, args, m)
| Expr.Obj (_, ty, basev, createExpr, overrides, iimpls, m) ->
OptimizeObjectExpr cenv env (ty, basev, createExpr, overrides, iimpls, m)
| Expr.Op (op, tyargs, args, m) ->
OptimizeExprOp cenv env (op, tyargs, args, m)
| Expr.App(f, fty, tyargs, argsl, m) ->
// eliminate uses of query
match TryDetectQueryQuoteAndRun cenv expr with
| Some newExpr -> OptimizeExpr cenv env newExpr
| None -> OptimizeApplication cenv env (f, fty, tyargs, argsl, m)
(* REVIEW: fold the next two cases together *)
| Expr.Lambda(_lambdaId, _, _, argvs, _body, m, rty) ->
let topValInfo = ValReprInfo ([], [argvs |> List.map (fun _ -> ValReprInfo.unnamedTopArg1)], ValReprInfo.unnamedRetVal)
let ty = mkMultiLambdaTy m argvs rty
OptimizeLambdas None cenv env topValInfo expr ty
| Expr.TyLambda(_lambdaId, tps, _body, _m, rty) ->
let topValInfo = ValReprInfo (ValReprInfo.InferTyparInfo tps, [], ValReprInfo.unnamedRetVal)
let ty = mkForallTyIfNeeded tps rty
OptimizeLambdas None cenv env topValInfo expr ty
| Expr.TyChoose _ -> OptimizeExpr cenv env (TypeRelations.ChooseTyparSolutionsForFreeChoiceTypars cenv.g cenv.amap expr)
| Expr.Match(spMatch, exprm, dtree, targets, m, ty) -> OptimizeMatch cenv env (spMatch, exprm, dtree, targets, m, ty)
| Expr.LetRec (binds, e, m, _) -> OptimizeLetRec cenv env (binds, e, m)
| Expr.StaticOptimization (constraints, e2, e3, m) ->
let e2', e2info = OptimizeExpr cenv env e2
let e3', e3info = OptimizeExpr cenv env e3
Expr.StaticOptimization(constraints, e2', e3', m),
| Expr.TyChoose _ ->
OptimizeExpr cenv env (TypeRelations.ChooseTyparSolutionsForFreeChoiceTypars cenv.g cenv.amap expr)
| Expr.Match(spMatch, exprm, dtree, targets, m, ty) ->
OptimizeMatch cenv env (spMatch, exprm, dtree, targets, m, ty)
| Expr.LetRec (binds, bodyExpr, m, _) ->
OptimizeLetRec cenv env (binds, bodyExpr, m)
| Expr.StaticOptimization (constraints, expr2, expr3, m) ->
let expr2R, e2info = OptimizeExpr cenv env expr2
let expr3R, e3info = OptimizeExpr cenv env expr3
Expr.StaticOptimization(constraints, expr2R, expr3R, m),
{ TotalSize = min e2info.TotalSize e3info.TotalSize
FunctionSize = min e2info.FunctionSize e3info.FunctionSize
HasEffect = e2info.HasEffect || e3info.HasEffect
MightMakeCriticalTailcall=e2info.MightMakeCriticalTailcall || e3info.MightMakeCriticalTailcall // seems conservative
Info= UnknownValue }
| Expr.Link _eref ->
assert ("unexpected reclink" = "")
failwith "Unexpected reclink"
......@@ -1851,7 +1889,9 @@ and OptimizeObjectExpr cenv env (ty, baseValOpt, basecall, overrides, iimpls, m)
// Optimize/analyze the methods that make up an object expression
//-------------------------------------------------------------------------
and OptimizeMethods cenv env baseValOpt l = OptimizeList (OptimizeMethod cenv env baseValOpt) l
and OptimizeMethods cenv env baseValOpt methods =
OptimizeList (OptimizeMethod cenv env baseValOpt) methods
and OptimizeMethod cenv env baseValOpt (TObjExprMethod(slotsig, attribs, tps, vs, e, m) as tmethod) =
let env = {env with latestBoundId=Some tmethod.Id; functionVal = None}
let env = BindTypeVarsToUnknown tps env
......@@ -1866,11 +1906,11 @@ and OptimizeMethod cenv env baseValOpt (TObjExprMethod(slotsig, attribs, tps, vs
MightMakeCriticalTailcall=false
Info=UnknownValue}
//-------------------------------------------------------------------------
// Optimize/analyze the interface implementations that form part of an object expression
//-------------------------------------------------------------------------
/// Optimize/analyze the interface implementations that form part of an object expression
and OptimizeInterfaceImpls cenv env baseValOpt iimpls =
OptimizeList (OptimizeInterfaceImpl cenv env baseValOpt) iimpls
and OptimizeInterfaceImpls cenv env baseValOpt l = OptimizeList (OptimizeInterfaceImpl cenv env baseValOpt) l
/// Optimize/analyze the interface implementations that form part of an object expression
and OptimizeInterfaceImpl cenv env baseValOpt (ty, overrides) =
let overrides', overridesinfos = OptimizeMethods cenv env baseValOpt overrides
(ty, overrides'),
......@@ -1880,13 +1920,10 @@ and OptimizeInterfaceImpl cenv env baseValOpt (ty, overrides) =
MightMakeCriticalTailcall=false
Info=UnknownValue}
//-------------------------------------------------------------------------
// Make and optimize String.Concat calls
//-------------------------------------------------------------------------
/// Make and optimize String.Concat calls
and MakeOptimizedSystemStringConcatCall cenv env m args =
let rec optimizeArg e accArgs =
match e, accArgs with
let rec optimizeArg argExpr accArgs =
match argExpr, accArgs with
| Expr.Op(TOp.ILCall(_, _, _, _, _, _, _, methRef, _, _, _), _, [ Expr.Op(TOp.Array, _, args, _) ], _), _ when IsSystemStringConcatArray methRef ->
optimizeArgs args accArgs
......@@ -1905,7 +1942,7 @@ and MakeOptimizedSystemStringConcatCall cenv env m args =
let args = optimizeArgs args []
let e =
let expr =
match args with
| [ arg ] ->
arg
......@@ -1919,11 +1956,11 @@ and MakeOptimizedSystemStringConcatCall cenv env m args =
let arg = mkArray (cenv.g.string_ty, args, m)
mkStaticCall_String_Concat_Array cenv.g m arg
match e with
match expr with
| Expr.Op(TOp.ILCall(_, _, _, _, _, _, _, methRef, _, _, _) as op, tyargs, args, m) when IsSystemStringConcatOverload methRef || IsSystemStringConcatArray methRef ->
OptimizeExprOpReductions cenv env (op, tyargs, args, m)
| _ ->
OptimizeExpr cenv env e
OptimizeExpr cenv env expr
//-------------------------------------------------------------------------
// Optimize/analyze an application of an intrinsic operator to arguments
......@@ -1933,11 +1970,11 @@ and OptimizeExprOp cenv env (op, tyargs, args, m) =
// Special cases
match op, tyargs, args with
| TOp.Coerce, [toty;fromty], [e] ->
let e', einfo = OptimizeExpr cenv env e
if typeEquiv cenv.g toty fromty then e', einfo
| TOp.Coerce, [toty;fromty], [arg] ->
let argR, einfo = OptimizeExpr cenv env arg
if typeEquiv cenv.g toty fromty then argR, einfo
else
mkCoerceExpr(e', toty, m, fromty),
mkCoerceExpr(argR, toty, m, fromty),
{ TotalSize=einfo.TotalSize + 1
FunctionSize=einfo.FunctionSize + 1
HasEffect = true
......@@ -2004,6 +2041,9 @@ and OptimizeExprOp cenv env (op, tyargs, args, m) =
and OptimizeExprOpReductions cenv env (op, tyargs, args, m) =
let args', arginfos = OptimizeExprsThenConsiderSplits cenv env args
OptimizeExprOpReductionsAfter cenv env (op, tyargs, args', arginfos, m)
and OptimizeExprOpReductionsAfter cenv env (op, tyargs, args', arginfos, m) =
let knownValue =
match op, arginfos with
| TOp.ValFieldGet (rf), [e1info] -> TryOptimizeRecordFieldGet cenv env (e1info, rf, tyargs, m)
......@@ -2210,15 +2250,15 @@ and OptimizeLetRec cenv env (binds, bodyExpr, m) =
let info = CombineValueInfos (einfo :: bindinfos) evalue'
bodyExpr', info
//-------------------------------------------------------------------------
// Optimize/analyze a linear sequence of sequentioanl execution or 'let' bindings.
//-------------------------------------------------------------------------
/// Optimize/analyze a linear sequence of sequential execution or 'let' bindings.
and OptimizeLinearExpr cenv env expr contf =
// Eliminate subsumption coercions for functions. This must be done post-typechecking because we need
// complete inference types.
let expr = DetectAndOptimizeForExpression cenv.g OptimizeAllForExpressions expr
let expr = if cenv.settings.ExpandStructrualValues() then ExpandStructuralBinding cenv expr else expr
let expr = stripExpr expr
match expr with
| Expr.Sequential (e1, e2, flag, spSeq, m) ->
let e1', e1info = OptimizeExpr cenv env e1
......@@ -2252,24 +2292,31 @@ and OptimizeLinearExpr cenv env expr contf =
MightMakeCriticalTailcall = bodyInfo.MightMakeCriticalTailcall // discard tailcall info from binding - not in tailcall position
Info = UnknownValue }
else
(* On the way back up: Trim out any optimization info that involves escaping values on the way back up *)
// On the way back up: Trim out any optimization info that involves escaping values on the way back up
let evalue' = AbstractExprInfoByVars ([bind'.Var], []) bodyInfo.Info
body',
{ TotalSize = bindingInfo.TotalSize + bodyInfo.TotalSize - localVarSize (* eliminated a local var *)
{ TotalSize = bindingInfo.TotalSize + bodyInfo.TotalSize - localVarSize // eliminated a local var
FunctionSize = bindingInfo.FunctionSize + bodyInfo.FunctionSize - localVarSize (* eliminated a local var *)
HasEffect=bindingInfo.HasEffect || bodyInfo.HasEffect
MightMakeCriticalTailcall = bodyInfo.MightMakeCriticalTailcall // discard tailcall info from binding - not in tailcall position
Info = evalue' } ))
| LinearMatchExpr (spMatch, exprm, dtree, tg1, e2, spTarget2, m, ty) ->
let dtree, dinfo = OptimizeDecisionTree cenv env m dtree
let dtree', dinfo = OptimizeDecisionTree cenv env m dtree
let tg1, tg1info = OptimizeDecisionTreeTarget cenv env m tg1
// tailcall
OptimizeLinearExpr cenv env e2 (contf << (fun (e2, e2info) ->
// This ConsiderSplitToMethod is performed because it is present in OptimizeDecisionTreeTarget
let e2, e2info = ConsiderSplitToMethod cenv.settings.abstractBigTargets cenv.settings.bigTargetSize cenv env (e2, e2info)
let tinfos = [tg1info; e2info]
let tgs = [tg1; TTarget([], e2, spTarget2)]
RebuildOptimizedMatch (spMatch, exprm, m, ty, dtree, tgs, dinfo, tinfos)))
let targets' = [tg1; TTarget([], e2, spTarget2)]
OptimizeMatchPart2 cenv (spMatch, exprm, dtree', targets', dinfo, tinfos, m, ty)))
| LinearOpExpr (op, tyargs, argsHead, argLast, m) ->
let argsHead', argsHeadInfos' = OptimizeList (OptimizeExprThenConsiderSplit cenv env) argsHead
// tailcall
OptimizeLinearExpr cenv env argLast (contf << (fun (argLast', argLastInfo) ->
OptimizeExprOpReductionsAfter cenv env (op, tyargs, argsHead' @ [argLast'], argsHeadInfos' @ [argLastInfo], m)))
| _ -> contf (OptimizeExpr cenv env expr)
......@@ -2916,7 +2963,6 @@ and OptimizeExprsThenConsiderSplits cenv env exprs =
| [] -> NoExprs
| _ -> OptimizeList (OptimizeExprThenConsiderSplit cenv env) exprs
and OptimizeExprThenReshapeAndConsiderSplit cenv env (shape, e) =
OptimizeExprThenConsiderSplit cenv env (ReshapeExpr cenv (shape, e))
......@@ -2994,6 +3040,9 @@ and OptimizeMatch cenv env (spMatch, exprm, dtree, targets, m, ty) =
// REVIEW: consider collecting, merging and using information flowing through each line of the decision tree to each target
let dtree', dinfo = OptimizeDecisionTree cenv env m dtree
let targets', tinfos = OptimizeDecisionTreeTargets cenv env m targets
OptimizeMatchPart2 cenv (spMatch, exprm, dtree', targets', dinfo, tinfos, m, ty)
and OptimizeMatchPart2 cenv (spMatch, exprm, dtree', targets', dinfo, tinfos, m, ty) =
let newExpr, newInfo = RebuildOptimizedMatch (spMatch, exprm, m, ty, dtree', targets', dinfo, tinfos)
let newExpr2 = if not (cenv.settings.localOpt()) then newExpr else CombineBoolLogic newExpr
newExpr2, newInfo
......@@ -3011,27 +3060,20 @@ and RebuildOptimizedMatch (spMatch, exprm, m, ty, dtree, tgs, dinfo, tinfos) =
let einfo = CombineMatchInfos dinfo tinfo
expr, einfo
//-------------------------------------------------------------------------
// Optimize/analyze a target of a decision tree
//-------------------------------------------------------------------------
and OptimizeDecisionTreeTarget cenv env _m (TTarget(vs, e, spTarget)) =
(* REVIEW: this is where we should be using information collected for each target *)
/// Optimize/analyze a target of a decision tree
and OptimizeDecisionTreeTarget cenv env _m (TTarget(vs, expr, spTarget)) =
let env = BindInternalValsToUnknown cenv vs env
let e', einfo = OptimizeExpr cenv env e
let e', einfo = ConsiderSplitToMethod cenv.settings.abstractBigTargets cenv.settings.bigTargetSize cenv env (e', einfo)
let expr', einfo = OptimizeExpr cenv env expr
let expr', einfo = ConsiderSplitToMethod cenv.settings.abstractBigTargets cenv.settings.bigTargetSize cenv env (expr', einfo)
let evalue' = AbstractExprInfoByVars (vs, []) einfo.Info
TTarget(vs, e', spTarget),
TTarget(vs, expr', spTarget),
{ TotalSize=einfo.TotalSize
FunctionSize=einfo.FunctionSize
HasEffect=einfo.HasEffect
MightMakeCriticalTailcall = einfo.MightMakeCriticalTailcall
Info=evalue' }
//-------------------------------------------------------------------------
// Optimize/analyze a decision tree
//-------------------------------------------------------------------------
/// Optimize/analyze a decision tree
and OptimizeDecisionTree cenv env m x =
match x with
| TDSuccess (es, n) ->
......
......@@ -879,27 +879,12 @@ and CheckCallWithReceiver cenv env m returnTy args contexts context =
limitArgs
CheckCallLimitArgs cenv env m returnTy limitArgs context
/// Check an expression, given information about the position of the expression
and CheckExpr (cenv:cenv) (env:env) origExpr (context:PermitByRefExpr) : Limit =
let g = cenv.g
let origExpr = stripExpr origExpr
// CheckForOverAppliedExceptionRaisingPrimitive is more easily checked prior to NormalizeAndAdjustPossibleSubsumptionExprs
CheckForOverAppliedExceptionRaisingPrimitive cenv origExpr
let expr = NormalizeAndAdjustPossibleSubsumptionExprs g origExpr
let expr = stripExpr expr
and CheckExprLinear (cenv:cenv) (env:env) expr (context:PermitByRefExpr) (contf : Limit -> Limit) =
match expr with
| Expr.Sequential (e1,e2,dir,_,_) ->
| Expr.Sequential (e1,e2,NormalSeq,_,_) ->
CheckExprNoByrefs cenv env e1
match dir with
| NormalSeq ->
CheckExpr cenv env e2 context // carry context into _;RHS (normal sequencing only)
| ThenDoSeq ->
CheckExprNoByrefs cenv {env with ctorLimitedZone=false} e2
NoLimit
// tailcall
CheckExprLinear cenv env e2 context contf
| Expr.Let ((TBind(v,_bindRhs,_) as bind),body,_,_) ->
let isByRef = isByrefTy cenv.g v.Type
......@@ -913,7 +898,48 @@ and CheckExpr (cenv:cenv) (env:env) origExpr (context:PermitByRefExpr) : Limit =
let limit = CheckBinding cenv { env with returnScope = env.returnScope + 1 } false bindingContext bind
BindVal cenv env v
LimitVal cenv v { limit with scope = if isByRef then limit.scope else env.returnScope }
CheckExpr cenv env body context
// tailcall
CheckExprLinear cenv env body context contf
| LinearOpExpr (_op, tyargs, argsHead, argLast, m) ->
CheckTypeInstNoByrefs cenv env m tyargs
argsHead |> List.iter (CheckExprNoByrefs cenv env)
// tailcall
CheckExprLinear cenv env argLast PermitByRefExpr.No (fun _ -> contf NoLimit)
| LinearMatchExpr (_spMatch, _exprm, dtree, tg1, e2, _spTarget2, m, ty) ->
CheckTypeNoInnerByrefs cenv env m ty
CheckDecisionTree cenv env dtree
let lim1 = CheckDecisionTreeTarget cenv env context tg1
// tailcall
CheckExprLinear cenv env e2 context (fun lim2 -> contf (CombineLimits [ lim1; lim2 ]))
| _ ->
// not a linear expression
contf (CheckExpr cenv env expr context)
/// Check an expression, given information about the position of the expression
and CheckExpr (cenv:cenv) (env:env) origExpr (context:PermitByRefExpr) : Limit =
let g = cenv.g
let origExpr = stripExpr origExpr
// CheckForOverAppliedExceptionRaisingPrimitive is more easily checked prior to NormalizeAndAdjustPossibleSubsumptionExprs
CheckForOverAppliedExceptionRaisingPrimitive cenv origExpr
let expr = NormalizeAndAdjustPossibleSubsumptionExprs g origExpr
let expr = stripExpr expr
match expr with
| LinearOpExpr _
| LinearMatchExpr _
| Expr.Let _
| Expr.Sequential (_, _, NormalSeq, _, _) ->
CheckExprLinear cenv env expr context id
| Expr.Sequential (e1,e2,ThenDoSeq,_,_) ->
CheckExprNoByrefs cenv env e1
CheckExprNoByrefs cenv {env with ctorLimitedZone=false} e2
NoLimit
| Expr.Const (_,m,ty) ->
CheckTypeNoInnerByrefs cenv env m ty
......
此差异已折叠。
......@@ -1357,7 +1357,7 @@ module DebugPrint =
/// A set of function parameters (visitor) for folding over expressions
type ExprFolder<'State> =
{ exprIntercept : ('State -> Expr -> 'State) -> 'State -> Expr -> 'State option
{ exprIntercept : (* recurseF *) ('State -> Expr -> 'State) -> (* noInterceptF *) ('State -> Expr -> 'State) -> 'State -> Expr -> 'State
valBindingSiteIntercept : 'State -> bool * Val -> 'State
nonRecBindingsIntercept : 'State -> Binding -> 'State
recBindingsIntercept : 'State -> Bindings -> 'State
......@@ -2261,6 +2261,10 @@ val (|LinearMatchExpr|_|) : Expr -> (SequencePointInfoForBinding * range * Decis
val rebuildLinearMatchExpr : (SequencePointInfoForBinding * range * DecisionTree * DecisionTreeTarget * Expr * SequencePointInfoForTarget * range * TType) -> Expr
val (|LinearOpExpr|_|) : Expr -> (TOp * TypeInst * Expr list * Expr * range) option
val rebuildLinearOpExpr : (TOp * TypeInst * Expr list * Expr * range) -> Expr
val mkCoerceIfNeeded : TcGlobals -> tgtTy: TType -> srcTy: TType -> Expr -> Expr
val (|InnerExprPat|) : Expr -> Expr
......
......@@ -6048,32 +6048,8 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) =
UnifyTypes cenv env m overallTy cenv.g.unit_ty
TcStmtThatCantBeCtorBody cenv env tpenv synInnerExpr
| SynExpr.IfThenElse (synBoolExpr, synThenExpr, synElseExprOpt, spIfToThen, isRecovery, mIfToThen, m) ->
let boolExpr, tpenv = TcExprThatCantBeCtorBody cenv cenv.g.bool_ty env tpenv synBoolExpr
let thenExpr, tpenv =
let env =
match env.eContextInfo with
| ContextInfo.ElseBranchResult _ -> { env with eContextInfo = ContextInfo.ElseBranchResult synThenExpr.Range }
| _ ->
match synElseExprOpt with
| None -> { env with eContextInfo = ContextInfo.OmittedElseBranch synThenExpr.Range }
| _ -> { env with eContextInfo = ContextInfo.IfExpression synThenExpr.Range }
if not isRecovery && Option.isNone synElseExprOpt then
UnifyTypes cenv env m cenv.g.unit_ty overallTy
TcExprThatCanBeCtorBody cenv overallTy env tpenv synThenExpr
let elseExpr, spElse, tpenv =
match synElseExprOpt with
| None ->
mkUnit cenv.g mIfToThen, SuppressSequencePointAtTarget, tpenv // the fake 'unit' value gets exactly the same range as spIfToThen
| Some synElseExpr ->
let env = { env with eContextInfo = ContextInfo.ElseBranchResult synElseExpr.Range }
let elseExpr, tpenv = TcExprThatCanBeCtorBody cenv overallTy env tpenv synElseExpr
elseExpr, SequencePointAtTarget, tpenv
primMkCond spIfToThen SequencePointAtTarget spElse m overallTy boolExpr thenExpr elseExpr, tpenv
| SynExpr.IfThenElse _ ->
TcLinearExprs (TcExprThatCanBeCtorBody cenv) cenv env overallTy tpenv false synExpr (fun x -> x)
// This is for internal use in the libraries only
| SynExpr.LibraryOnlyStaticOptimization (constraints, e2, e3, m) ->
......@@ -10440,6 +10416,7 @@ and TcLinearExprs bodyChecker cenv env overallTy tpenv isCompExpr expr cont =
let e1', _ = TcStmtThatCantBeCtorBody cenv env tpenv e1
// tailcall
let env = ShrinkContext env m e2.Range
// tailcall
TcLinearExprs bodyChecker cenv env overallTy tpenv isCompExpr e2 (fun (e2', tpenv) ->
cont (Expr.Sequential(e1', e2', NormalSeq, sp, m), tpenv))
......@@ -10457,8 +10434,40 @@ and TcLinearExprs bodyChecker cenv env overallTy tpenv isCompExpr expr cont =
// TcLinearExprs processes multiple 'let' bindings in a tail recursive way
let mkf, envinner, tpenv = TcLetBinding cenv isUse env ExprContainerInfo ExpressionBinding tpenv (binds, m, body.Range)
let envinner = ShrinkContext envinner m body.Range
// tailcall
TcLinearExprs bodyChecker cenv envinner overallTy tpenv isCompExpr body (fun (x, tpenv) ->
cont (fst (mkf (x, overallTy)), tpenv))
| SynExpr.IfThenElse (synBoolExpr, synThenExpr, synElseExprOpt, spIfToThen, isRecovery, mIfToThen, m) when not isCompExpr ->
let boolExpr, tpenv = TcExprThatCantBeCtorBody cenv cenv.g.bool_ty env tpenv synBoolExpr
let thenExpr, tpenv =
let env =
match env.eContextInfo with
| ContextInfo.ElseBranchResult _ -> { env with eContextInfo = ContextInfo.ElseBranchResult synThenExpr.Range }
| _ ->
match synElseExprOpt with
| None -> { env with eContextInfo = ContextInfo.OmittedElseBranch synThenExpr.Range }
| _ -> { env with eContextInfo = ContextInfo.IfExpression synThenExpr.Range }
if not isRecovery && Option.isNone synElseExprOpt then
UnifyTypes cenv env m cenv.g.unit_ty overallTy
TcExprThatCanBeCtorBody cenv overallTy env tpenv synThenExpr
match synElseExprOpt with
| None ->
let elseExpr = mkUnit cenv.g mIfToThen
let spElse = SuppressSequencePointAtTarget // the fake 'unit' value gets exactly the same range as spIfToThen
let overallExpr = primMkCond spIfToThen SequencePointAtTarget spElse m overallTy boolExpr thenExpr elseExpr
cont (overallExpr, tpenv)
| Some synElseExpr ->
let env = { env with eContextInfo = ContextInfo.ElseBranchResult synElseExpr.Range }
// tailcall
TcLinearExprs bodyChecker cenv env overallTy tpenv isCompExpr synElseExpr (fun (elseExpr, tpenv) ->
let resExpr = primMkCond spIfToThen SequencePointAtTarget SequencePointAtTarget m overallTy boolExpr thenExpr elseExpr
cont (resExpr, tpenv))
| _ ->
cont (bodyChecker overallTy env tpenv expr)
......
......@@ -44,41 +44,39 @@ let DecideLambda exprF cenv topValInfo expr ety z =
| _ -> z
///Special cases where representation uses Lambda.
let DecideExprOp exprF z (op, tyargs, args) =
(* Special cases *)
/// Handle these as special cases since mutables are allowed inside their bodies
let DecideExprOp exprF noInterceptF (z: Zset<Val>) (expr: Expr) (op, tyargs, args) =
match op, tyargs, args with
// Handle these as special cases since mutables are allowed inside their bodies
| TOp.While _, _, [Expr.Lambda(_, _, _, [_], e1, _, _);Expr.Lambda(_, _, _, [_], e2, _, _)] ->
Some (exprF (exprF z e1) e2)
exprF (exprF z e1) e2
| TOp.TryFinally _, [_], [Expr.Lambda(_, _, _, [_], e1, _, _); Expr.Lambda(_, _, _, [_], e2, _, _)] ->
Some (exprF (exprF z e1) e2)
exprF (exprF z e1) e2
| TOp.For(_), _, [Expr.Lambda(_, _, _, [_], e1, _, _);Expr.Lambda(_, _, _, [_], e2, _, _);Expr.Lambda(_, _, _, [_], e3, _, _)] ->
Some (exprF (exprF (exprF z e1) e2) e3)
exprF (exprF (exprF z e1) e2) e3
| TOp.TryCatch _, [_], [Expr.Lambda(_, _, _, [_], e1, _, _); Expr.Lambda(_, _, _, [_], _e2, _, _); Expr.Lambda(_, _, _, [_], e3, _, _)] ->
Some (exprF (exprF (exprF z e1) _e2) e3)
exprF (exprF (exprF z e1) _e2) e3
// In Check code it said
// e2; -- don't check filter body - duplicates logic in 'catch' body
// Is that true for this code too?
| _ -> None
| _ ->
noInterceptF z expr
/// Find all the mutable locals that escape a lambda expression or object expression
let DecideExpr cenv exprF z expr =
let DecideExpr cenv exprF noInterceptF z expr =
match expr with
| Expr.Lambda(_, _ctorThisValOpt, _baseValOpt, argvs, _, m, rty) ->
let topValInfo = ValReprInfo ([], [argvs |> List.map (fun _ -> ValReprInfo.unnamedTopArg1)], ValReprInfo.unnamedRetVal)
let ty = mkMultiLambdaTy m argvs rty
let z = DecideLambda (Some exprF) cenv topValInfo expr ty z
Some z
DecideLambda (Some exprF) cenv topValInfo expr ty z
| Expr.TyLambda(_, tps, _, _m, rty) ->
let topValInfo = ValReprInfo (ValReprInfo.InferTyparInfo tps, [], ValReprInfo.unnamedRetVal)
let ty = mkForallTyIfNeeded tps rty
let z = DecideLambda (Some exprF) cenv topValInfo expr ty z
Some z
DecideLambda (Some exprF) cenv topValInfo expr ty z
| Expr.Obj (_, _, baseValOpt, superInitCall, overrides, iimpls, _m) ->
let CheckMethod z (TObjExprMethod(_, _attribs, _tps, vs, body, _m)) =
......@@ -94,12 +92,13 @@ let DecideExpr cenv exprF z expr =
let z = exprF z superInitCall
let z = CheckMethods z overrides
let z = (z, iimpls) ||> List.fold CheckInterfaceImpl
Some z
z
| Expr.Op (c, tyargs, args, _m) ->
DecideExprOp exprF z (c, tyargs, args)
DecideExprOp exprF noInterceptF z expr (c, tyargs, args)
| _ -> None
| _ ->
noInterceptF z expr
/// Find all the mutable locals that escape a binding
let DecideBinding cenv z (TBind(v, expr, _m) as bind) =
......
module TestData
let rnd = new System.Random()
let expectedValues() =
let x = 1
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
4
printfn "expectedValues() = %A" (expectedValues())
System.IO.File.WriteAllLines("test.ok", ["ok"])
\ No newline at end of file
module TestData
let rnd = new System.Random()
let expectedValues() =
let x = 1
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
if rnd.Next(3) = 1 then 1 else
4
printfn "expectedValues() = %A" (expectedValues())
System.IO.File.WriteAllLines("test.ok", ["ok"])
\ No newline at end of file
module TestData
let rnd = new System.Random()
let expectedValues() =
let x = 1
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
let x = x + rnd.Next(3)
x
printfn "expectedValues() = %A" (expectedValues())
System.IO.File.WriteAllLines("test.ok", ["ok"])
此差异已折叠。
module TestData
let expectedValues =
[
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
]
printfn "length = %d" expectedValues.Length
System.IO.File.WriteAllLines("test.ok", ["ok"])
\ No newline at end of file
module TestData
let rnd = new System.Random()
let r() = if rnd.Next(3) > 1 then Some 4 else None
let expectedValues() =
let x = 1
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
match r() with
| Some x -> x
| None ->
4
printfn "expectedValues() = %A" (expectedValues())
System.IO.File.WriteAllLines("test.ok", ["ok"])
\ No newline at end of file
此差异已折叠。
......@@ -273,6 +273,94 @@ module CoreTests =
testOkFile.CheckExists()
[<Test>]
let ``lots-of-conditionals``() =
let cfg = testConfig "core/large/conditionals"
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe " cfg.fsc_flags ["LargeConditionals-200.fs"]
exec cfg ("." ++ "test.exe") ""
testOkFile.CheckExists()
[<Test>]
let ``lots-of-conditionals-maxtested``() =
let cfg = testConfig "core/large/conditionals"
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe " cfg.fsc_flags ["LargeConditionals-maxtested.fs"]
exec cfg ("." ++ "test.exe") ""
testOkFile.CheckExists()
[<Test>]
let ``lots-of-lets``() =
let cfg = testConfig "core/large/lets"
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe " cfg.fsc_flags ["LargeLets-500.fs"]
exec cfg ("." ++ "test.exe") ""
testOkFile.CheckExists()
[<Test>]
let ``lots-of-lets-maxtested``() =
let cfg = testConfig "core/large/lets"
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe " cfg.fsc_flags ["LargeLets-maxtested.fs"]
exec cfg ("." ++ "test.exe") ""
testOkFile.CheckExists()
[<Test>]
let ``lots-of-lists``() =
let cfg = testConfig "core/large/lists"
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test-500.exe " cfg.fsc_flags ["LargeList-500.fs"]
exec cfg ("." ++ "test-500.exe") ""
testOkFile.CheckExists()
[<Test>]
let ``lots-of-matches``() =
let cfg = testConfig "core/large/matches"
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe " cfg.fsc_flags ["LargeMatches-200.fs"]
exec cfg ("." ++ "test.exe") ""
testOkFile.CheckExists()
[<Test>]
let ``lots-of-matches-maxtested``() =
let cfg = testConfig "core/large/matches"
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe " cfg.fsc_flags ["LargeMatches-maxtested.fs"]
exec cfg ("." ++ "test.exe") ""
testOkFile.CheckExists()
[<Test>]
let ``lots-of-sequential-and-let``() =
let cfg = testConfig "core/large/mixed"
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe " cfg.fsc_flags ["LargeSequentialLet-500.fs"]
exec cfg ("." ++ "test.exe") ""
testOkFile.CheckExists()
[<Test>]
let ``lots-of-sequential-and-let-maxtested``() =
let cfg = testConfig "core/large/mixed"
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe " cfg.fsc_flags ["LargeSequentialLet-maxtested.fs"]
exec cfg ("." ++ "test.exe") ""
testOkFile.CheckExists()
[<Test>]
let ``lots-of-sequential``() =
let cfg = testConfig "core/large/sequential"
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe " cfg.fsc_flags ["LargeSequential-500.fs"]
exec cfg ("." ++ "test.exe") ""
testOkFile.CheckExists()
[<Test>]
let ``lots-of-sequential-maxtested``() =
let cfg = testConfig "core/large/sequential"
use testOkFile = fileguard cfg "test.ok"
fsc cfg "%s -o:test.exe " cfg.fsc_flags ["LargeSequential-maxtested.fs"]
exec cfg ("." ++ "test.exe") ""
testOkFile.CheckExists()
#endif
[<Test>]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册