From 419bccf0624fc0d28392ade9970cd6b3c4d2c716 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 27 Jul 2021 14:49:21 +0100 Subject: [PATCH 1/2] indexer notation expr[expr] --- src/fsharp/CheckComputationExpressions.fs | 83 +++- src/fsharp/CheckComputationExpressions.fsi | 4 +- src/fsharp/CheckDeclarations.fs | 4 +- src/fsharp/CheckExpressions.fs | 463 +++++++++++------- src/fsharp/CheckExpressions.fsi | 10 +- src/fsharp/CompilerDiagnostics.fs | 5 +- src/fsharp/ErrorLogger.fs | 6 + src/fsharp/ErrorLogger.fsi | 6 + src/fsharp/FSComp.txt | 7 +- .../FSharp.Compiler.Service.fsproj | 2 +- src/fsharp/LanguageFeatures.fs | 11 + src/fsharp/LanguageFeatures.fsi | 4 + src/fsharp/LexFilter.fs | 107 ++-- src/fsharp/LowerCallsAndSeqs.fs | 2 +- src/fsharp/SyntaxTree.fs | 47 +- src/fsharp/SyntaxTree.fsi | 53 +- src/fsharp/SyntaxTreeOps.fs | 29 +- src/fsharp/SyntaxTreeOps.fsi | 6 +- src/fsharp/fsi/fsi.fs | 2 +- src/fsharp/pars.fsy | 353 ++++++------- src/fsharp/range.fs | 9 +- src/fsharp/range.fsi | 6 + src/fsharp/service/FSharpParseFileResults.fs | 21 +- .../service/ServiceInterfaceStubGenerator.fs | 21 +- src/fsharp/service/ServiceParseTreeWalk.fs | 30 +- src/fsharp/service/ServiceParsedInputOps.fs | 145 +++--- src/fsharp/service/ServiceStructure.fs | 14 +- src/fsharp/service/ServiceStructure.fsi | 2 +- src/fsharp/xlf/FSComp.txt.cs.xlf | 29 +- src/fsharp/xlf/FSComp.txt.de.xlf | 29 +- src/fsharp/xlf/FSComp.txt.es.xlf | 29 +- src/fsharp/xlf/FSComp.txt.fr.xlf | 29 +- src/fsharp/xlf/FSComp.txt.it.xlf | 29 +- src/fsharp/xlf/FSComp.txt.ja.xlf | 29 +- src/fsharp/xlf/FSComp.txt.ko.xlf | 29 +- src/fsharp/xlf/FSComp.txt.pl.xlf | 29 +- src/fsharp/xlf/FSComp.txt.pt-BR.xlf | 29 +- src/fsharp/xlf/FSComp.txt.ru.xlf | 29 +- src/fsharp/xlf/FSComp.txt.tr.xlf | 29 +- src/fsharp/xlf/FSComp.txt.zh-Hans.xlf | 29 +- src/fsharp/xlf/FSComp.txt.zh-Hant.xlf | 29 +- .../Conformance/LexicalAnalysis/Comments.fs | 4 +- .../ErrorMessages/SuggestionsTests.fs | 1 - .../ErrorMessages/WrongSyntaxInForLoop.fs | 2 +- tests/FSharp.Test.Utilities/Compiler.fs | 2 +- tests/fsharp/tests.fs | 36 +- .../EmittedIL/Misc/CodeGenRenamings01.il.bsl | 1 - .../fsc/flaterrors/E_MultiLine01.fs | 2 +- .../fsc/flaterrors/E_MultiLine02.fs | 2 +- ...ValueIsNotAFunctionAndCannotBeApplied01.fs | 7 - .../Source/Diagnostics/General/env.lst | 2 - .../Misc/E_RangeOperator01.fsx | 2 +- tests/service/EditorTests.fs | 10 - .../Structure/BlockStructureService.fs | 4 +- vsintegration/tests/Salsa/salsa.fs | 14 + 55 files changed, 1227 insertions(+), 691 deletions(-) delete mode 100644 tests/fsharpqa/Source/Diagnostics/General/E_ThisValueIsNotAFunctionAndCannotBeApplied01.fs diff --git a/src/fsharp/CheckComputationExpressions.fs b/src/fsharp/CheckComputationExpressions.fs index 1ca65d4599a..c7faaff4d8d 100644 --- a/src/fsharp/CheckComputationExpressions.fs +++ b/src/fsharp/CheckComputationExpressions.fs @@ -928,6 +928,10 @@ let TcComputationExpression cenv env overallTy tpenv (mWhole, interpExpr: Expr, | SynExpr.ForEach (spForLoop, SeqExprOnly _seqExprOnly, isFromSource, pat, sourceExpr, innerComp, _) -> + let sourceExpr = + match RewriteRangeExpr sourceExpr with + | Some e -> e + | None -> sourceExpr let wrappedSourceExpr = mkSourceExprConditional isFromSource sourceExpr let mFor = match spForLoop with DebugPointAtFor.Yes m -> m.NoteDebugPoint(RangeDebugPointKind.For) | _ -> pat.Range let mPat = pat.Range @@ -1726,6 +1730,10 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp overallTy m = let rec tryTcSequenceExprBody env genOuterTy tpenv comp = match comp with | SynExpr.ForEach (spFor, SeqExprOnly _seqExprOnly, _isFromSource, pat, pseudoEnumExpr, innerComp, m) -> + let pseudoEnumExpr = + match RewriteRangeExpr pseudoEnumExpr with + | Some e -> e + | None -> pseudoEnumExpr // This expression is not checked with the knowledge it is an IEnumerable, since we permit other enumerable types with GetEnumerator/MoveNext methods, as does C# let pseudoEnumExpr, arb_ty, tpenv = TcExprOfUnknownType cenv env tpenv pseudoEnumExpr let enumExpr, enumElemTy = ConvertArbitraryExprToEnumerable cenv arb_ty env pseudoEnumExpr @@ -1931,31 +1939,70 @@ let TcSequenceExpression (cenv: cenv) env tpenv comp overallTy m = let delayedExpr = mkDelayedExpr coreExpr.Range coreExpr delayedExpr, tpenv -let TcSequenceExpressionEntry (cenv: cenv) env overallTy tpenv (isArrayOrList, isNotNakedRefCell, comp) m = +let TcSequenceExpressionEntry (cenv: cenv) env overallTy tpenv (hasBuilder, comp) m = + match RewriteRangeExpr comp with + | Some replacementExpr -> + TcExpr cenv overallTy env tpenv replacementExpr + | None -> + let implicitYieldEnabled = cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield let validateObjectSequenceOrRecordExpression = not implicitYieldEnabled - if not isArrayOrList then - match comp with - | SynExpr.New _ -> - errorR(Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm(), m)) - | SimpleSemicolonSequence cenv false _ when validateObjectSequenceOrRecordExpression -> - errorR(Error(FSComp.SR.tcInvalidObjectSequenceOrRecordExpression(), m)) - | _ -> - () - if not !isNotNakedRefCell && not cenv.g.compilingFslib then + match comp with + | SynExpr.New _ -> + errorR(Error(FSComp.SR.tcInvalidObjectExpressionSyntaxForm(), m)) + | SimpleSemicolonSequence cenv false _ when validateObjectSequenceOrRecordExpression -> + errorR(Error(FSComp.SR.tcInvalidObjectSequenceOrRecordExpression(), m)) + | _ -> + () + if not hasBuilder && not cenv.g.compilingFslib then error(Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm(), m)) TcSequenceExpression cenv env tpenv comp overallTy m -let TcArrayOrListSequenceExpression (cenv: cenv) env overallTy tpenv (isArray, comp) m = +let TcArrayOrListComputedExpression (cenv: cenv) env overallTy tpenv (isArray, comp) m = + // The syntax '[ n .. m ]' and '[ n .. step .. m ]' is not really part of array or list syntax. + // It could be in the future, e.g. '[ 1; 2..30; 400 ]' + // + // The elaborated form of '[ n .. m ]' is 'List.ofSeq (seq (op_Range n m))' and this shouldn't change + match RewriteRangeExpr comp with + | Some replacementExpr -> + let genCollElemTy = NewInferenceType () + + let genCollTy = (if isArray then mkArrayType else mkListTy) cenv.g genCollElemTy + + UnifyTypes cenv env m overallTy genCollTy + + let exprTy = mkSeqTy cenv.g genCollElemTy + + let expr, tpenv = TcExpr cenv exprTy env tpenv replacementExpr + let expr = + if cenv.g.compilingFslib then + //warning(Error(FSComp.SR.fslibUsingComputedListOrArray(), expr.Range)) + expr + else + // We add a call to 'seq ... ' to make sure sequence expression compilation gets applied to the contents of the + // comprehension. But don't do this in FSharp.Core.dll since 'seq' may not yet be defined. + mkCallSeq cenv.g m genCollElemTy expr + + let expr = mkCoerceExpr(expr, exprTy, expr.Range, overallTy) + + let expr = + if isArray then + mkCallSeqToArray cenv.g m genCollElemTy expr + else + mkCallSeqToList cenv.g m genCollElemTy expr + expr, tpenv + + | None -> + // LanguageFeatures.ImplicitYield do not require this validation let implicitYieldEnabled = cenv.g.langVersion.SupportsFeature LanguageFeature.ImplicitYield let validateExpressionWithIfRequiresParenthesis = not implicitYieldEnabled let acceptDeprecatedIfThenExpression = not implicitYieldEnabled match comp with - | SynExpr.CompExpr (_, _, (SimpleSemicolonSequence cenv acceptDeprecatedIfThenExpression elems as body), _) -> - match body with + | SimpleSemicolonSequence cenv acceptDeprecatedIfThenExpression elems -> + match comp with | SimpleSemicolonSequence cenv false _ -> () | _ when validateExpressionWithIfRequiresParenthesis -> errorR(Deprecated(FSComp.SR.tcExpressionWithIfRequiresParenthesis(), m)) | _ -> () @@ -1983,12 +2030,12 @@ let TcArrayOrListSequenceExpression (cenv: cenv) env overallTy tpenv (isArray, c UnifyTypes cenv env m overallTy genCollTy - let exprty = mkSeqTy cenv.g genCollElemTy + let exprTy = mkSeqTy cenv.g genCollElemTy - // Check the comprehension - let expr, tpenv = TcExpr cenv exprty env tpenv comp + // Check the comprehension as a sequence + let expr, tpenv = TcSequenceExpression cenv env tpenv comp exprTy m - let expr = mkCoerceIfNeeded cenv.g exprty (tyOfExpr cenv.g expr) expr + let expr = mkCoerceIfNeeded cenv.g exprTy (tyOfExpr cenv.g expr) expr let expr = if cenv.g.compilingFslib then @@ -1999,7 +2046,7 @@ let TcArrayOrListSequenceExpression (cenv: cenv) env overallTy tpenv (isArray, c // comprehension. But don't do this in FSharp.Core.dll since 'seq' may not yet be defined. mkCallSeq cenv.g m genCollElemTy expr - let expr = mkCoerceExpr(expr, exprty, expr.Range, overallTy) + let expr = mkCoerceExpr(expr, exprTy, expr.Range, overallTy) let expr = if isArray then diff --git a/src/fsharp/CheckComputationExpressions.fsi b/src/fsharp/CheckComputationExpressions.fsi index a6c8a46d136..68060a05481 100644 --- a/src/fsharp/CheckComputationExpressions.fsi +++ b/src/fsharp/CheckComputationExpressions.fsi @@ -7,9 +7,9 @@ open FSharp.Compiler.Syntax open FSharp.Compiler.Text open FSharp.Compiler.TypedTree -val TcSequenceExpressionEntry: cenv:TcFileState -> env:TcEnv -> overallTy:TType -> tpenv:UnscopedTyparEnv -> isArrayOrList:bool * isNotNakedRefCell:bool ref * comp:SynExpr -> m:range -> Expr * UnscopedTyparEnv +val TcSequenceExpressionEntry: cenv:TcFileState -> env:TcEnv -> overallTy:TType -> tpenv:UnscopedTyparEnv -> hasBuilder:bool * comp:SynExpr -> m:range -> Expr * UnscopedTyparEnv -val TcArrayOrListSequenceExpression: cenv:TcFileState -> env:TcEnv -> overallTy:TType -> tpenv:UnscopedTyparEnv -> isArray:bool * comp:SynExpr -> m:range -> Expr * UnscopedTyparEnv +val TcArrayOrListComputedExpression: cenv:TcFileState -> env:TcEnv -> overallTy:TType -> tpenv:UnscopedTyparEnv -> isArray:bool * comp:SynExpr -> m:range -> Expr * UnscopedTyparEnv val TcComputationExpression: cenv:TcFileState -> env:TcEnv -> overallTy:TType -> tpenv:UnscopedTyparEnv -> mWhole:range * interpExpr:Expr * builderTy:TType * comp:SynExpr -> Expr * UnscopedTyparEnv diff --git a/src/fsharp/CheckDeclarations.fs b/src/fsharp/CheckDeclarations.fs index df6b0bf4c14..21cac722197 100644 --- a/src/fsharp/CheckDeclarations.fs +++ b/src/fsharp/CheckDeclarations.fs @@ -5806,7 +5806,7 @@ let TypeCheckOneImplFile cenv.Create (g, isScript, niceNameGen, amap, topCcu, false, Option.isSome rootSigOpt, conditionalDefines, tcSink, (LightweightTcValForUsingInBuildMethodCall g), isInternalTestSpanStackReferring, tcSequenceExpressionEntry=TcSequenceExpressionEntry, - tcArrayOrListSequenceExpression=TcArrayOrListSequenceExpression, + tcArrayOrListSequenceExpression=TcArrayOrListComputedExpression, tcComputationExpression=TcComputationExpression) let envinner, mtypeAcc = MakeInitialEnv env @@ -5913,7 +5913,7 @@ let TypeCheckOneSigFile (g, niceNameGen, amap, topCcu, checkForErrors, condition (g, false, niceNameGen, amap, topCcu, true, false, conditionalDefines, tcSink, (LightweightTcValForUsingInBuildMethodCall g), isInternalTestSpanStackReferring, tcSequenceExpressionEntry=TcSequenceExpressionEntry, - tcArrayOrListSequenceExpression=TcArrayOrListSequenceExpression, + tcArrayOrListSequenceExpression=TcArrayOrListComputedExpression, tcComputationExpression=TcComputationExpression) let envinner, mtypeAcc = MakeInitialEnv tcEnv diff --git a/src/fsharp/CheckExpressions.fs b/src/fsharp/CheckExpressions.fs index 7566a18ae94..e6482fe0585 100644 --- a/src/fsharp/CheckExpressions.fs +++ b/src/fsharp/CheckExpressions.fs @@ -406,9 +406,9 @@ type TcFileState = isInternalTestSpanStackReferring: bool // forward call - TcSequenceExpressionEntry: TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> bool * bool ref * SynExpr -> range -> Expr * UnscopedTyparEnv + TcSequenceExpressionEntry: TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> bool * SynExpr -> range -> Expr * UnscopedTyparEnv // forward call - TcArrayOrListSequenceExpression: TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> bool * SynExpr -> range -> Expr * UnscopedTyparEnv + TcArrayOrListComputedExpression: TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> bool * SynExpr -> range -> Expr * UnscopedTyparEnv // forward call TcComputationExpression: TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> range * Expr * TType * SynExpr -> Expr * UnscopedTyparEnv } @@ -439,7 +439,7 @@ type TcFileState = conditionalDefines = conditionalDefines isInternalTestSpanStackReferring = isInternalTestSpanStackReferring TcSequenceExpressionEntry = tcSequenceExpressionEntry - TcArrayOrListSequenceExpression = tcArrayOrListSequenceExpression + TcArrayOrListComputedExpression = tcArrayOrListSequenceExpression TcComputationExpression = tcComputationExpression } @@ -3688,15 +3688,11 @@ let buildApp cenv expr resultTy arg m = //------------------------------------------------------------------------- type DelayedItem = - /// DelayedTypeApp (typeArgs, mTypeArgs, mExprAndTypeArgs) - /// /// Represents the in "item" - | DelayedTypeApp of SynType list * range * range + | DelayedTypeApp of typeArgs: SynType list * mTypeArgs: range * mExprAndTypeArgs: range - /// DelayedApp (isAtomic, argExpr, mFuncAndArg) - /// - /// Represents the args in "item args", or "item.[args]". - | DelayedApp of ExprAtomicFlag * SynExpr * range + /// Represents the args in "item args", or "item.Property(args)". + | DelayedApp of isAtomic: ExprAtomicFlag * funcExprForIndexer: SynExpr option * argExpr: SynExpr * mFuncAndArg: range /// Represents the long identifiers in "item.Ident1", or "item.Ident1.Ident2" etc. | DelayedDotLookup of Ident list * range @@ -3770,6 +3766,9 @@ type ValSpecResult = partialValReprInfo: PartialValReprInfo * declKind: DeclKind +type DecodedIndexArg = + | IndexArgRange of (SynExpr * bool) option * (SynExpr * bool) option * range * range + | IndexArgItem of SynExpr * bool * range //------------------------------------------------------------------------- // Additional data structures used by checking recursive bindings //------------------------------------------------------------------------- @@ -5011,7 +5010,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p let activePatResTys = NewInferenceTypes apinfo.Names let activePatType = apinfo.OverallType cenv.g m ty activePatResTys isStructRetTy - let delayed = activePatArgsAsSynExprs |> List.map (fun arg -> DelayedApp(ExprAtomicFlag.NonAtomic, arg, unionRanges (rangeOfLid longId) arg.Range)) + let delayed = activePatArgsAsSynExprs |> List.map (fun arg -> DelayedApp(ExprAtomicFlag.NonAtomic, None, arg, unionRanges (rangeOfLid longId) arg.Range)) let activePatExpr, tpenv = PropagateThenTcDelayed cenv activePatType env tpenv m vexp vexpty ExprAtomicFlag.NonAtomic delayed if idx >= activePatResTys.Length then error(Error(FSComp.SR.tcInvalidIndexIntoActivePatternArray(), m)) @@ -5269,7 +5268,7 @@ and RecordNameAndTypeResolutions_IdeallyWithoutHavingOtherEffects_Delayed cenv e let rec dummyCheckedDelayed delayed = match delayed with - | DelayedApp (_hpa, arg, _mExprAndArg) :: otherDelayed -> + | DelayedApp (_hpa, _, arg, _mExprAndArg) :: otherDelayed -> RecordNameAndTypeResolutions_IdeallyWithoutHavingOtherEffects cenv env tpenv arg dummyCheckedDelayed otherDelayed | _ -> () @@ -5394,7 +5393,7 @@ and TcExprThen cenv overallTy env tpenv synExpr delayed = // f x | SynExpr.App (hpa, _, func, arg, mFuncAndArg) -> - TcExprThen cenv overallTy env tpenv func ((DelayedApp (hpa, arg, mFuncAndArg)) :: delayed) + TcExprThen cenv overallTy env tpenv func ((DelayedApp (hpa, Some func, arg, mFuncAndArg)) :: delayed) // e | SynExpr.TypeApp (func, _, typeArgs, _, _, mTypeArgs, mFuncAndTypeArgs) -> @@ -5409,14 +5408,18 @@ and TcExprThen cenv overallTy env tpenv synExpr delayed = // e1.[e2] // e1.[e21, ..., e2n] // etc. - | SynExpr.DotIndexedGet (e1, e2, mDot, mWholeExpr) -> - TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv synExpr e1 e2 delayed + | SynExpr.DotIndexedGet (e1, IndexerArgs indexArgs, mDot, mWholeExpr) -> + if cenv.g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot then + warning(Error(FSComp.SR.tcIndexNotationDeprecated(), mDot)) + TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv None e1 indexArgs delayed // e1.[e2] <- e3 // e1.[e21, ..., e2n] <- e3 // etc. - | SynExpr.DotIndexedSet (e1, e2, _, _, mDot, mWholeExpr) -> - TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv synExpr e1 e2 delayed + | SynExpr.DotIndexedSet (e1, IndexerArgs indexArgs, e3, mOfLeftOfSet, mDot, mWholeExpr) -> + if cenv.g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot then + warning(Error(FSComp.SR.tcIndexNotationDeprecated(), mDot)) + TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv (Some (e3, mOfLeftOfSet)) e1 indexArgs delayed | _ -> match delayed with @@ -5449,6 +5452,11 @@ and TcExprUndelayedNoType cenv env tpenv synExpr: Expr * TType * _ = and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = match synExpr with + // ( * ) + | SynExpr.Paren(SynExpr.IndexRange (None, opm, None, _m1, _m2, _), _, _, _) -> + let replacementExpr = SynExpr.Ident(ident(CompileOpName "*", opm)) + TcExpr cenv overallTy env tpenv replacementExpr + | SynExpr.Paren (expr2, _, _, mWholeExprIncludingParentheses) -> // We invoke CallExprHasTypeSink for every construct which is atomic in the syntax, i.e. where a '.' immediately following the // construct is a dot-lookup for the result of the construct. @@ -5645,15 +5653,20 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = | SynExpr.ForEach (spForLoop, SeqExprOnly seqExprOnly, isFromSource, pat, enumSynExpr, bodySynExpr, m) -> assert isFromSource if seqExprOnly then warning (Error(FSComp.SR.tcExpressionRequiresSequence(), m)) + let enumSynExpr = + match RewriteRangeExpr enumSynExpr with + | Some e -> e + | None -> enumSynExpr TcForEachExpr cenv overallTy env tpenv (pat, enumSynExpr, bodySynExpr, m, spForLoop) - | SynExpr.CompExpr (isArrayOrList, isNotNakedRefCell, comp, m) -> + | SynExpr.ComputationExpr (hasSeqBuilder, comp, m) -> let env = ExitFamilyRegion env - cenv.TcSequenceExpressionEntry cenv env overallTy tpenv (isArrayOrList, isNotNakedRefCell, comp) m + cenv.TcSequenceExpressionEntry cenv env overallTy tpenv (hasSeqBuilder, comp) m - | SynExpr.ArrayOrListOfSeqExpr (isArray, comp, m) -> + | SynExpr.ArrayOrListComputed (isArray, comp, m) -> + let env = ExitFamilyRegion env CallExprHasTypeSink cenv.tcSink (m, env.NameEnv, overallTy, env.eAccessRights) - cenv.TcArrayOrListSequenceExpression cenv env overallTy tpenv (isArray, comp) m + cenv.TcArrayOrListComputedExpression cenv env overallTy tpenv (isArray, comp) m | SynExpr.LetOrUse _ -> TcLinearExprs (TcExprThatCanBeCtorBody cenv) cenv env overallTy tpenv false synExpr (fun x -> x) @@ -5755,7 +5768,7 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = TcExprThen cenv overallTy env tpenv e1 [DelayedDotLookup(longId, mExprAndDotLookup)] else let mExprAndDotLookup = unionRanges e1.Range (rangeOfLid longId) - TcExprThen cenv overallTy env tpenv e1 [DelayedDotLookup(longId, mExprAndDotLookup); DelayedApp(ExprAtomicFlag.Atomic, e2, mStmt); MakeDelayedSet(e3, mStmt)] + TcExprThen cenv overallTy env tpenv e1 [DelayedDotLookup(longId, mExprAndDotLookup); DelayedApp(ExprAtomicFlag.Atomic, None, e2, mStmt); MakeDelayedSet(e3, mStmt)] | SynExpr.LongIdentSet (lidwd, e2, m) -> if lidwd.ThereIsAnExtraDotAtTheEnd then @@ -5770,7 +5783,7 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = // just drop rhs on the floor TcLongIdentThen cenv overallTy env tpenv lidwd [ ] else - TcLongIdentThen cenv overallTy env tpenv lidwd [ DelayedApp(ExprAtomicFlag.Atomic, e1, mStmt); MakeDelayedSet(e2, mStmt) ] + TcLongIdentThen cenv overallTy env tpenv lidwd [ DelayedApp(ExprAtomicFlag.Atomic, None, e1, mStmt); MakeDelayedSet(e2, mStmt) ] | SynExpr.TraitCall (tps, memSpfn, arg, m) -> let synTypes = tps |> List.map (fun tp -> SynType.Var(tp, m)) @@ -5850,6 +5863,31 @@ and TcExprUndelayed cenv overallTy env tpenv (synExpr: SynExpr) = | SynExpr.MatchBang (_, _, _, m) -> error(Error(FSComp.SR.tcConstructRequiresComputationExpression(), m)) + | SynExpr.IndexFromEnd (range=m) + | SynExpr.IndexRange (range=m) -> + error(Error(FSComp.SR.tcInvalidIndexerExpression(), m)) + +// Converts 'a..b' to a call to the '(..)' operator in FSharp.Core +// Converts 'a..b..c' to a call to the '(.. ..)' operator in FSharp.Core +// +// NOTE: we could eliminate these more efficiently in LowerCallsAndSeqs.fs, since +// [| 1..4 |] +// becomes [| for i in (..) 1 4 do yield i |] +// instead of generating the array directly from the ranges +and RewriteRangeExpr expr = + match expr with + // a..b..c (parsed as (a..b)..c ) + | SynExpr.IndexRange(Some (SynExpr.IndexRange(Some expr1, _, Some synStepExpr, _, _, _)), _, Some expr2, _m1, _m2, wholem) -> + Some (mkSynTrifix wholem ".. .." expr1 synStepExpr expr2) + // a..b + | SynExpr.IndexRange (Some expr1, opm, Some expr2, _m1, _m2, wholem) -> + let otherExpr = + match mkSynInfix opm expr1 ".." expr2 with + | SynExpr.App (a, b, c, d, _) -> SynExpr.App (a, b, c, d, wholem) + | _ -> failwith "impossible" + Some otherExpr + | _ -> None + /// Check lambdas as a group, to catch duplicate names in patterns and TcIteratedLambdas cenv isFirst (env: TcEnv) overallTy takenNames tpenv e = match e with @@ -5886,19 +5924,95 @@ and TcIteratedLambdas cenv isFirst (env: TcEnv) overallTy takenNames tpenv e = //TcExprFlex cenv true true overallTy env tpenv e) TcExpr cenv overallTy env tpenv e) +and (|IndexArgOptionalFromEnd|) indexArg = + match indexArg with + | SynExpr.IndexFromEnd (a, m) -> (a, true, m) + | expr -> (expr, false, expr.Range) + +and DecodeIndexArg indexArg = + match indexArg with + | SynExpr.IndexRange (info1, _opm, info2, m1, m2, _) -> + let info1 = + match info1 with + | Some (IndexArgOptionalFromEnd (expr1, isFromEnd1, _)) -> Some (expr1, isFromEnd1) + | None -> None + let info2 = + match info2 with + | Some (IndexArgOptionalFromEnd (expr2, isFromEnd2, _)) -> Some (expr2, isFromEnd2) + | None -> None + IndexArgRange (info1, info2, m1, m2) + | IndexArgOptionalFromEnd (expr, isFromEnd, m) -> + IndexArgItem(expr, isFromEnd, m) + +and (|IndexerArgs|) e = + match e with + | SynExpr.IndexRange _ -> [e] + | SynExpr.IndexFromEnd _ -> [e] + | SynExpr.Tuple (false, args, _, _) -> args + | e -> [e] + +and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv (setInfo: _ option) e1 indexArgs delayed = + let e1', e1ty, tpenv = TcExprOfUnknownType cenv env tpenv e1 + let expandedIndexArgs = ExpandIndexArgs (Some e1) indexArgs + TcIndexingThen cenv env overallTy mWholeExpr mDot tpenv setInfo (Some e1) e1' e1ty expandedIndexArgs indexArgs delayed + +// Eliminate GetReverseIndex from index args +and ExpandIndexArgs (synLeftExpr: SynExpr option) indexArgs = + + // xs.GetReverseIndex rank offset - 1 + let rewriteReverseExpr (rank: int) (offset: SynExpr) (range: range) = + let rankExpr = SynExpr.Const(SynConst.Int32(rank), range) + let sliceArgs = SynExpr.Paren(SynExpr.Tuple(false, [rankExpr; offset], [], range), range, Some range, range) + match synLeftExpr with + | None -> error(Error(FSComp.SR.tcInvalidUseOfReverseIndex(), range)) + | Some xsId -> + mkSynApp1 + (mkSynDot range range xsId (mkSynId (range.MakeSynthetic()) "GetReverseIndex")) + sliceArgs + range + + let mkSynSomeExpr (m: range) x = + let m = m.MakeSynthetic() + SynExpr.App (ExprAtomicFlag.NonAtomic, false, mkSynLidGet m FSharpLib.CorePath "Some", x, m) + + let mkSynNoneExpr (m: range) = + let m = m.MakeSynthetic() + mkSynLidGet m FSharpLib.CorePath "None" + + let expandedIndexArgs = + indexArgs + |> List.mapi ( fun pos indexerArg -> + match DecodeIndexArg indexerArg with + | IndexArgItem(expr, fromEnd, range) -> + [ if fromEnd then rewriteReverseExpr pos expr range else expr ] + | IndexArgRange(info1, info2, range1, range2) -> + [ + match info1 with + | Some (a1, isFromEnd1) -> + yield mkSynSomeExpr range1 (if isFromEnd1 then rewriteReverseExpr pos a1 range1 else a1) + | None -> + yield mkSynNoneExpr range1 + match info2 with + | Some (a2, isFromEnd2) -> + yield mkSynSomeExpr range2 (if isFromEnd2 then rewriteReverseExpr pos a2 range2 else a2) + | None -> + yield mkSynNoneExpr range1 + ] + ) + |> List.collect id + + expandedIndexArgs // Check expr.[idx] // This is a little over complicated for my liking. Basically we want to interpret e1.[idx] as e1.Item(idx). // However it's not so simple as all that. First "Item" can have a different name according to an attribute in // .NET metadata. This means we manually typecheck 'e1' and look to see if it has a nominal type. We then // do the right thing in each case. -and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArgs delayed = +and TcIndexingThen cenv env overallTy mWholeExpr mDot tpenv setInfo synLeftExpr e1' e1ty expandedIndexArgs indexArgs delayed = let ad = env.AccessRights - let e1', e1ty, tpenv = TcExprOfUnknownType cenv env tpenv e1 - // Find the first type in the effective hierarchy that either has a DefaultMember attribute OR // has a member called 'Item' - let isIndex = indexArgs |> List.forall( fun x -> match x with SynIndexerArg.One _ -> true | _ -> false) + let isIndex = indexArgs |> List.forall (fun indexArg -> match DecodeIndexArg indexArg with IndexArgItem _ -> true | _ -> false) let propName = if isIndex then FoldPrimaryHierarchyOfType (fun ty acc -> @@ -5928,47 +6042,10 @@ and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArg let idxRange = indexArgs |> List.map (fun e -> e.Range) |> List.reduce unionRanges - // xs.GetReverseIndex rank offset - 1 - let rewriteReverseExpr (rank: int) (offset: SynExpr) (range: range) = - let rankExpr = SynExpr.Const(SynConst.Int32(rank), range) - let sliceArgs = SynExpr.Paren(SynExpr.Tuple(false, [rankExpr; offset], [], range), range, Some range, range) - let xsId = e1 - - mkSynApp1 - (mkSynDot range range xsId (mkSynId range "GetReverseIndex")) - sliceArgs - range - - let rewriteReverseOption (app: SynExpr) (rank: int) (range: range) = - match app with - | SynExpr.App(atomicFlag, isInfix, funcExpr, e1, outerRange) -> SynExpr.App(atomicFlag, isInfix, funcExpr, rewriteReverseExpr rank e1 range, outerRange) - | _ -> app - - let expandedIndexArgs = - indexArgs - |> List.mapi ( fun pos indexerArg -> - match indexerArg with - | SynIndexerArg.One(expr, fromEnd, range) -> - [ if fromEnd then rewriteReverseExpr pos expr range else expr ] - | SynIndexerArg.Two - ( - a1, - fromEnd1, - a2, - fromEnd2, - range1, - range2) -> - [ - if fromEnd1 then rewriteReverseOption a1 pos range1 else a1 ; - if fromEnd2 then rewriteReverseOption a2 pos range2 else a2 - ] - ) - |> List.collect id - let MakeIndexParam setSliceArrayOption = - match indexArgs with + match List.map DecodeIndexArg indexArgs with | [] -> failwith "unexpected empty index list" - | [SynIndexerArg.One _] -> SynExpr.Paren (expandedIndexArgs.Head, range0, None, idxRange) + | [IndexArgItem _] -> SynExpr.Paren (expandedIndexArgs.Head, range0, None, idxRange) | _ -> SynExpr.Paren (SynExpr.Tuple (false, expandedIndexArgs @ Option.toList setSliceArrayOption, [], idxRange), range0, None, idxRange) let attemptArrayString = @@ -5978,76 +6055,77 @@ and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArg let info = if isArray then let fixedIndex3d4dEnabled = cenv.g.langVersion.SupportsFeature LanguageFeature.FixedIndexSlice3d4d - match wholeExpr with - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _; SynIndexerArg.One _], _, _) -> Some (indexOpPath, "GetArray2D", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _; SynIndexerArg.One _; SynIndexerArg.One _;], _, _) -> Some (indexOpPath, "GetArray3D", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _; SynIndexerArg.One _; SynIndexerArg.One _; SynIndexerArg.One _], _, _) -> Some (indexOpPath, "GetArray4D", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _], _, _) -> Some (indexOpPath, "GetArray", expandedIndexArgs) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _; SynIndexerArg.One _], e3, _, _, _) -> Some (indexOpPath, "SetArray2D", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _; SynIndexerArg.One _; SynIndexerArg.One _;], e3, _, _, _) -> Some (indexOpPath, "SetArray3D", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _; SynIndexerArg.One _; SynIndexerArg.One _; SynIndexerArg.One _], e3, _, _, _) -> Some (indexOpPath, "SetArray4D", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _], e3, _, _, _) -> Some (indexOpPath, "SetArray", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice2DFixed1", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.One _], _, _) -> Some (sliceOpPath, "GetArraySlice2DFixed2", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice2D", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice3D", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice4D", expandedIndexArgs) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice2D", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice2DFixed1", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.One _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice2DFixed2", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice3D", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4D", (expandedIndexArgs @ [e3])) - | _ when fixedIndex3d4dEnabled -> - match wholeExpr with - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice3DFixedSingle1", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice3DFixedSingle2", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.One _], _, _) -> Some (sliceOpPath, "GetArraySlice3DFixedSingle3", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice3DFixedDouble1", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.One _], _, _) -> Some (sliceOpPath, "GetArraySlice3DFixedDouble2", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.One _], _, _) -> Some (sliceOpPath, "GetArraySlice3DFixedDouble3", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedSingle1", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedSingle2", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedSingle3", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.One _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedSingle4", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedDouble1", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedDouble2", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.One _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedDouble3", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedDouble4", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.One _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedDouble5", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.One _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedDouble6", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.One _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedTriple1", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.One _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedTriple2", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.One _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedTriple3", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetArraySlice4DFixedTriple4", expandedIndexArgs) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice3DFixedSingle1", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice3DFixedSingle2", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.One _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice3DFixedSingle3", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice3DFixedDouble1", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.One _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice3DFixedDouble2", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.One _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice3DFixedDouble3", (expandedIndexArgs @ [e3])) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedSingle1", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedSingle2", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedSingle3", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.One _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedSingle4", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble1", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble2", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.One _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble3", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble4", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.One _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble5", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.One _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble6", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.One _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedTriple1", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.One _;SynIndexerArg.One _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedTriple2", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.Two _;SynIndexerArg.One _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedTriple3", expandedIndexArgs @ [e3]) - | SynExpr.DotIndexedSet (_, [SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.One _;SynIndexerArg.Two _], e3, _, _, _) -> Some (sliceOpPath, "SetArraySlice4DFixedTriple4", expandedIndexArgs @ [e3]) - | _ -> None + let indexArgs = List.map DecodeIndexArg indexArgs + match indexArgs, setInfo with + | [IndexArgItem _; IndexArgItem _], None -> Some (indexOpPath, "GetArray2D", expandedIndexArgs) + | [IndexArgItem _; IndexArgItem _; IndexArgItem _;], None -> Some (indexOpPath, "GetArray3D", expandedIndexArgs) + | [IndexArgItem _; IndexArgItem _; IndexArgItem _; IndexArgItem _], None -> Some (indexOpPath, "GetArray4D", expandedIndexArgs) + | [IndexArgItem _], None -> Some (indexOpPath, "GetArray", expandedIndexArgs) + | [IndexArgItem _; IndexArgItem _], Some (e3, _) -> Some (indexOpPath, "SetArray2D", (expandedIndexArgs @ [e3])) + | [IndexArgItem _; IndexArgItem _; IndexArgItem _;], Some (e3, _) -> Some (indexOpPath, "SetArray3D", (expandedIndexArgs @ [e3])) + | [IndexArgItem _; IndexArgItem _; IndexArgItem _; IndexArgItem _], Some (e3, _) -> Some (indexOpPath, "SetArray4D", (expandedIndexArgs @ [e3])) + | [IndexArgItem _], Some (e3, _) -> Some (indexOpPath, "SetArray", (expandedIndexArgs @ [e3])) + | [IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice", expandedIndexArgs) + | [IndexArgItem _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice2DFixed1", expandedIndexArgs) + | [IndexArgRange _;IndexArgItem _], None -> Some (sliceOpPath, "GetArraySlice2DFixed2", expandedIndexArgs) + | [IndexArgRange _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice2D", expandedIndexArgs) + | [IndexArgRange _;IndexArgRange _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice3D", expandedIndexArgs) + | [IndexArgRange _;IndexArgRange _;IndexArgRange _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice4D", expandedIndexArgs) + | [IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice", (expandedIndexArgs @ [e3])) + | [IndexArgRange _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice2D", (expandedIndexArgs @ [e3])) + | [IndexArgItem _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice2DFixed1", (expandedIndexArgs @ [e3])) + | [IndexArgRange _;IndexArgItem _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice2DFixed2", (expandedIndexArgs @ [e3])) + | [IndexArgRange _;IndexArgRange _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice3D", (expandedIndexArgs @ [e3])) + | [IndexArgRange _;IndexArgRange _;IndexArgRange _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4D", (expandedIndexArgs @ [e3])) + | _ when fixedIndex3d4dEnabled -> + match indexArgs, setInfo with + | [IndexArgItem _;IndexArgRange _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice3DFixedSingle1", expandedIndexArgs) + | [IndexArgRange _;IndexArgItem _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice3DFixedSingle2", expandedIndexArgs) + | [IndexArgRange _;IndexArgRange _;IndexArgItem _], None -> Some (sliceOpPath, "GetArraySlice3DFixedSingle3", expandedIndexArgs) + | [IndexArgItem _;IndexArgItem _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice3DFixedDouble1", expandedIndexArgs) + | [IndexArgItem _;IndexArgRange _;IndexArgItem _], None -> Some (sliceOpPath, "GetArraySlice3DFixedDouble2", expandedIndexArgs) + | [IndexArgRange _;IndexArgItem _;IndexArgItem _], None -> Some (sliceOpPath, "GetArraySlice3DFixedDouble3", expandedIndexArgs) + | [IndexArgItem _;IndexArgRange _;IndexArgRange _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice4DFixedSingle1", expandedIndexArgs) + | [IndexArgRange _;IndexArgItem _;IndexArgRange _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice4DFixedSingle2", expandedIndexArgs) + | [IndexArgRange _;IndexArgRange _;IndexArgItem _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice4DFixedSingle3", expandedIndexArgs) + | [IndexArgRange _;IndexArgRange _;IndexArgRange _;IndexArgItem _], None -> Some (sliceOpPath, "GetArraySlice4DFixedSingle4", expandedIndexArgs) + | [IndexArgItem _;IndexArgItem _;IndexArgRange _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice4DFixedDouble1", expandedIndexArgs) + | [IndexArgItem _;IndexArgRange _;IndexArgItem _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice4DFixedDouble2", expandedIndexArgs) + | [IndexArgItem _;IndexArgRange _;IndexArgRange _;IndexArgItem _], None -> Some (sliceOpPath, "GetArraySlice4DFixedDouble3", expandedIndexArgs) + | [IndexArgRange _;IndexArgItem _;IndexArgItem _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice4DFixedDouble4", expandedIndexArgs) + | [IndexArgRange _;IndexArgItem _;IndexArgRange _;IndexArgItem _], None -> Some (sliceOpPath, "GetArraySlice4DFixedDouble5", expandedIndexArgs) + | [IndexArgRange _;IndexArgRange _;IndexArgItem _;IndexArgItem _], None -> Some (sliceOpPath, "GetArraySlice4DFixedDouble6", expandedIndexArgs) + | [IndexArgRange _;IndexArgItem _;IndexArgItem _;IndexArgItem _], None -> Some (sliceOpPath, "GetArraySlice4DFixedTriple1", expandedIndexArgs) + | [IndexArgItem _;IndexArgRange _;IndexArgItem _;IndexArgItem _], None -> Some (sliceOpPath, "GetArraySlice4DFixedTriple2", expandedIndexArgs) + | [IndexArgItem _;IndexArgItem _;IndexArgRange _;IndexArgItem _], None -> Some (sliceOpPath, "GetArraySlice4DFixedTriple3", expandedIndexArgs) + | [IndexArgItem _;IndexArgItem _;IndexArgItem _;IndexArgRange _], None -> Some (sliceOpPath, "GetArraySlice4DFixedTriple4", expandedIndexArgs) + | [IndexArgItem _;IndexArgRange _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice3DFixedSingle1", (expandedIndexArgs @ [e3])) + | [IndexArgRange _;IndexArgItem _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice3DFixedSingle2", (expandedIndexArgs @ [e3])) + | [IndexArgRange _;IndexArgRange _;IndexArgItem _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice3DFixedSingle3", (expandedIndexArgs @ [e3])) + | [IndexArgItem _;IndexArgItem _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice3DFixedDouble1", (expandedIndexArgs @ [e3])) + | [IndexArgItem _;IndexArgRange _;IndexArgItem _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice3DFixedDouble2", (expandedIndexArgs @ [e3])) + | [IndexArgRange _;IndexArgItem _;IndexArgItem _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice3DFixedDouble3", (expandedIndexArgs @ [e3])) + | [IndexArgItem _;IndexArgRange _;IndexArgRange _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedSingle1", expandedIndexArgs @ [e3]) + | [IndexArgRange _;IndexArgItem _;IndexArgRange _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedSingle2", expandedIndexArgs @ [e3]) + | [IndexArgRange _;IndexArgRange _;IndexArgItem _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedSingle3", expandedIndexArgs @ [e3]) + | [IndexArgRange _;IndexArgRange _;IndexArgRange _;IndexArgItem _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedSingle4", expandedIndexArgs @ [e3]) + | [IndexArgItem _;IndexArgItem _;IndexArgRange _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble1", expandedIndexArgs @ [e3]) + | [IndexArgItem _;IndexArgRange _;IndexArgItem _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble2", expandedIndexArgs @ [e3]) + | [IndexArgItem _;IndexArgRange _;IndexArgRange _;IndexArgItem _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble3", expandedIndexArgs @ [e3]) + | [IndexArgRange _;IndexArgItem _;IndexArgItem _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble4", expandedIndexArgs @ [e3]) + | [IndexArgRange _;IndexArgItem _;IndexArgRange _;IndexArgItem _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble5", expandedIndexArgs @ [e3]) + | [IndexArgRange _;IndexArgRange _;IndexArgItem _;IndexArgItem _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedDouble6", expandedIndexArgs @ [e3]) + | [IndexArgRange _;IndexArgItem _;IndexArgItem _;IndexArgItem _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedTriple1", expandedIndexArgs @ [e3]) + | [IndexArgItem _;IndexArgRange _;IndexArgItem _;IndexArgItem _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedTriple2", expandedIndexArgs @ [e3]) + | [IndexArgItem _;IndexArgItem _;IndexArgRange _;IndexArgItem _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedTriple3", expandedIndexArgs @ [e3]) + | [IndexArgItem _;IndexArgItem _;IndexArgItem _;IndexArgRange _], Some (e3, _) -> Some (sliceOpPath, "SetArraySlice4DFixedTriple4", expandedIndexArgs @ [e3]) | _ -> None + | _ -> None elif isString then - match wholeExpr with - | SynExpr.DotIndexedGet (_, [SynIndexerArg.Two _], _, _) -> Some (sliceOpPath, "GetStringSlice", expandedIndexArgs) - | SynExpr.DotIndexedGet (_, [SynIndexerArg.One _], _, _) -> Some (indexOpPath, "GetString", expandedIndexArgs) + match List.map DecodeIndexArg indexArgs, setInfo with + | [IndexArgRange _], None -> Some (sliceOpPath, "GetStringSlice", expandedIndexArgs) + | [IndexArgItem _], None -> Some (indexOpPath, "GetString", expandedIndexArgs) | _ -> None else None @@ -6055,12 +6133,12 @@ and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArg match info with | None -> None | Some (path, functionName, indexArgs) -> - let operPath = mkSynLidGet mDot path (CompileOpName functionName) + let operPath = mkSynLidGet (mDot.MakeSynthetic()) path (CompileOpName functionName) let f, fty, tpenv = TcExprOfUnknownType cenv env tpenv operPath let domainTy, resultTy = UnifyFunctionType (Some mWholeExpr) cenv env.DisplayEnv mWholeExpr fty UnifyTypes cenv env mWholeExpr domainTy e1ty let f', resultTy = buildApp cenv (MakeApplicableExprNoFlex cenv f) resultTy e1' mWholeExpr - let delayed = List.foldBack (fun idx acc -> DelayedApp(ExprAtomicFlag.Atomic, idx, mWholeExpr) :: acc) indexArgs delayed // atomic, otherwise no ar.[1] <- xyz + let delayed = List.foldBack (fun idx acc -> DelayedApp(ExprAtomicFlag.Atomic, None, idx, mWholeExpr) :: acc) indexArgs delayed // atomic, otherwise no ar.[1] <- xyz Some (PropagateThenTcDelayed cenv overallTy env tpenv mWholeExpr f' resultTy ExprAtomicFlag.Atomic delayed ) match attemptArrayString with @@ -6072,17 +6150,16 @@ and TcIndexerThen cenv env overallTy mWholeExpr mDot tpenv wholeExpr e1 indexArg | None -> "Item" | Some nm -> nm let delayed = - match wholeExpr with + match setInfo with // e1.[e2] - | SynExpr.DotIndexedGet _ -> - DelayedDotLookup([ident(nm, mWholeExpr)], mWholeExpr) :: DelayedApp(ExprAtomicFlag.Atomic, MakeIndexParam None, mWholeExpr) :: delayed + | None -> + DelayedDotLookup([ident(nm, mWholeExpr)], mWholeExpr) :: DelayedApp(ExprAtomicFlag.Atomic, synLeftExpr, MakeIndexParam None, mWholeExpr) :: delayed // e1.[e2] <- e3 - | SynExpr.DotIndexedSet (_, _, e3, mOfLeftOfSet, _, _) -> + | Some (e3, mOfLeftOfSet) -> match isIndex with - | true -> DelayedDotLookup([ident(nm, mOfLeftOfSet)], mOfLeftOfSet) :: DelayedApp(ExprAtomicFlag.Atomic, MakeIndexParam None, mOfLeftOfSet) :: MakeDelayedSet(e3, mWholeExpr) :: delayed - | false -> DelayedDotLookup([ident("SetSlice", mOfLeftOfSet)], mOfLeftOfSet) :: DelayedApp(ExprAtomicFlag.Atomic, MakeIndexParam (Some e3), mWholeExpr) :: delayed + | true -> DelayedDotLookup([ident(nm, mOfLeftOfSet)], mOfLeftOfSet) :: DelayedApp(ExprAtomicFlag.Atomic, synLeftExpr, MakeIndexParam None, mOfLeftOfSet) :: MakeDelayedSet(e3, mWholeExpr) :: delayed + | false -> DelayedDotLookup([ident("SetSlice", mOfLeftOfSet)], mOfLeftOfSet) :: DelayedApp(ExprAtomicFlag.Atomic, synLeftExpr, MakeIndexParam (Some e3), mWholeExpr) :: delayed - | _ -> error(InternalError("unreachable", mWholeExpr)) PropagateThenTcDelayed cenv overallTy env tpenv mDot (MakeApplicableExprNoFlex cenv e1') e1ty ExprAtomicFlag.Atomic delayed else @@ -7332,7 +7409,7 @@ and Propagate cenv overallTy env tpenv (expr: ApplicableExpr) exprty delayed = // Note this case should not occur: would eventually give an "Unexpected type application" error in TcDelayed propagate isAddrOf delayedList' mExprAndTypeArgs exprty - | DelayedApp (_, arg, mExprAndArg) :: delayedList' -> + | DelayedApp (atomicFlag, _, arg, mExprAndArg) :: delayedList' -> let denv = env.DisplayEnv match UnifyFunctionTypeUndoIfFailed cenv denv mExpr exprty with | ValueSome (_, resultTy) -> @@ -7351,8 +7428,17 @@ and Propagate cenv overallTy env tpenv (expr: ApplicableExpr) exprty delayed = | _ -> let mArg = arg.Range match arg with - | SynExpr.CompExpr _ -> () - | SynExpr.ArrayOrListOfSeqExpr (false, _, _) -> + | SynExpr.ComputationExpr _ -> () + | SynExpr.ArrayOrListComputed (false, _, _) -> + match atomicFlag with + | ExprAtomicFlag.Atomic when cenv.g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot -> + // expr[idx] + // expr[idx1, idx2] + // expr[idx1..] + // expr[..idx1] + // expr[idx1..idx2] + () + | _ -> // 'delayed' is about to be dropped on the floor, first do rudimentary checking to get name resolutions in its body RecordNameAndTypeResolutions_IdeallyWithoutHavingOtherEffects_Delayed cenv env tpenv delayed if IsIndexerType cenv.g cenv.amap expr.Type then @@ -7395,8 +7481,8 @@ and TcDelayed cenv overallTy env tpenv mExpr expr exprty (atomicFlag: ExprAtomic | DelayedDotLookup (longId, mDotLookup) :: otherDelayed -> TcLookupThen cenv overallTy env tpenv mExpr expr.Expr exprty longId otherDelayed mDotLookup // f x - | DelayedApp (hpa, arg, mExprAndArg) :: otherDelayed -> - TcFunctionApplicationThen cenv overallTy env tpenv mExprAndArg expr exprty arg hpa otherDelayed + | DelayedApp (hpa, synExpr, arg, mExprAndArg) :: otherDelayed -> + TcFunctionApplicationThen cenv overallTy env tpenv mExprAndArg synExpr expr exprty arg hpa otherDelayed // f | DelayedTypeApp (_, mTypeArgs, _mExprAndTypeArgs) :: _ -> error(Error(FSComp.SR.tcUnexpectedTypeArguments(), mTypeArgs)) @@ -7542,15 +7628,24 @@ and TcNameOfExprResult cenv (lastIdent: Ident) m = // TcFunctionApplicationThen: Typecheck "expr x" + projections //------------------------------------------------------------------------- -and TcFunctionApplicationThen cenv overallTy env tpenv mExprAndArg expr exprty (synArg: SynExpr) atomicFlag delayed = +and TcFunctionApplicationThen cenv overallTy env tpenv mExprAndArg synExpr expr exprty (synArg: SynExpr) atomicFlag delayed = let denv = env.DisplayEnv let mArg = synArg.Range let mFunExpr = expr.Range // If the type of 'synArg' unifies as a function type, then this is a function application, otherwise - // it is an error or a computation expression + // it is an error or a computation expression or indexer or delegate invoke match UnifyFunctionTypeUndoIfFailed cenv denv mFunExpr exprty with | ValueSome (domainTy, resultTy) -> + match synArg, atomicFlag with + // expr[idx] + | (SynExpr.ArrayOrList _ | SynExpr.ArrayOrListComputed _), ExprAtomicFlag.Atomic -> + if cenv.g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot then + warning(Error(FSComp.SR.tcHighPrecedenceFunctionApplicationToListDeprecated(), mExprAndArg)) + elif not (cenv.g.langVersion.IsExplicitlySpecifiedAs50OrBefore()) then + warning(Error(FSComp.SR.tcHighPrecedenceFunctionApplicationToListReserved(), mExprAndArg)) + | _ -> () + match expr with | ApplicableExpr(_, NameOfExpr cenv.g _, _) when cenv.g.langVersion.SupportsFeature LanguageFeature.NameOf -> let replacementExpr = TcNameOfExpr cenv env tpenv synArg @@ -7558,26 +7653,41 @@ and TcFunctionApplicationThen cenv overallTy env tpenv mExprAndArg expr exprty ( | _ -> // Notice the special case 'seq { ... }'. In this case 'seq' is actually a function in the F# library. // Set a flag in the syntax tree to say we noticed a leading 'seq' - match synArg with - | SynExpr.CompExpr (false, isNotNakedRefCell, _comp, _m) -> - isNotNakedRefCell := - !isNotNakedRefCell - || - (match expr with - | ApplicableExpr(_, Expr.Op(TOp.Coerce, _, [SeqExpr cenv.g], _), _) -> true - | _ -> false) - | _ -> () + // + // Note that 'seq' predated computation expressions and is not actually a computation expression builder + // though users don't realise that. + let synArg = + match synArg with + | SynExpr.ComputationExpr (false, comp, m) when + (match expr with + | ApplicableExpr(_, Expr.Op(TOp.Coerce, _, [SeqExpr cenv.g], _), _) -> true + | _ -> false) -> + SynExpr.ComputationExpr (true, comp, m) + | _ -> synArg let arg, tpenv = TcExpr cenv domainTy env tpenv synArg let exprAndArg, resultTy = buildApp cenv expr resultTy arg mExprAndArg TcDelayed cenv overallTy env tpenv mExprAndArg exprAndArg resultTy atomicFlag delayed | ValueNone -> - // OK, 'expr' doesn't have function type, but perhaps 'expr' is a computation expression builder, and 'arg' is '{ ... }' - match synArg with - | SynExpr.CompExpr (false, _isNotNakedRefCell, comp, _m) -> + // Type-directed invokables + + match synArg, atomicFlag with + // expr[idx] + // expr[idx] <- expr2 + | SynExpr.ArrayOrListComputed(false, IndexerArgs indexArgs, m), ExprAtomicFlag.Atomic when cenv.g.langVersion.SupportsFeature LanguageFeature.IndexerNotationWithoutDot -> + let expandedIndexArgs = ExpandIndexArgs synExpr indexArgs + let setInfo, delayed = + match delayed with + | DelayedSet(e3, _) :: rest -> Some (e3, unionRanges expr.Range synArg.Range), rest + | _ -> None, delayed + TcIndexingThen cenv env overallTy mExprAndArg m tpenv setInfo synExpr expr.Expr exprty expandedIndexArgs indexArgs delayed + + // Perhaps 'expr' is a computation expression builder, and 'arg' is '{ ... }' + | SynExpr.ComputationExpr (false, comp, _m), _ -> let bodyOfCompExpr, tpenv = cenv.TcComputationExpression cenv env overallTy tpenv (mFunExpr, expr.Expr, exprty, comp) TcDelayed cenv overallTy env tpenv mExprAndArg (MakeApplicableExprNoFlex cenv bodyOfCompExpr) (tyOfExpr cenv.g bodyOfCompExpr) ExprAtomicFlag.NonAtomic delayed + | _ -> error (NotAFunction(denv, overallTy, mFunExpr, mArg)) @@ -7652,7 +7762,7 @@ and TcItemThen cenv overallTy env tpenv (tinstEnclosing, item, mItem, rest, afte match delayed with // This is where the constructor is applied to an argument - | DelayedApp (atomicFlag, (FittedArgs args as origArg), mExprAndArg) :: otherDelayed -> + | DelayedApp (atomicFlag, _, (FittedArgs args as origArg), mExprAndArg) :: otherDelayed -> // assert the overall result type if possible if isNil otherDelayed then UnifyTypes cenv env mExprAndArg overallTy ucaseAppTy @@ -7798,7 +7908,7 @@ and TcItemThen cenv overallTy env tpenv (tinstEnclosing, item, mItem, rest, afte // Static method calls Type.Foo(arg1, ..., argn) let meths = List.map (fun minfo -> minfo, None) minfos match delayed with - | DelayedApp (atomicFlag, arg, mExprAndArg) :: otherDelayed -> + | DelayedApp (atomicFlag, _, arg, mExprAndArg) :: otherDelayed -> TcMethodApplicationThen cenv env overallTy None tpenv None [] mExprAndArg mItem methodName ad NeverMutates false meths afterResolution NormalValUse [arg] atomicFlag otherDelayed | DelayedTypeApp(tys, mTypeArgs, mExprAndTypeArgs) :: otherDelayed -> @@ -7812,7 +7922,7 @@ and TcItemThen cenv overallTy env tpenv (tinstEnclosing, item, mItem, rest, afte CallNameResolutionSinkReplacing cenv.tcSink (mItem, env.NameEnv, item, [], ItemOccurence.Use, env.eAccessRights) match otherDelayed with - | DelayedApp(atomicFlag, arg, mExprAndArg) :: otherDelayed -> + | DelayedApp(atomicFlag, _, arg, mExprAndArg) :: otherDelayed -> TcMethodApplicationThen cenv env overallTy None tpenv None [] mExprAndArg mItem methodName ad NeverMutates false [(minfoAfterStaticArguments, None)] afterResolution NormalValUse [arg] atomicFlag otherDelayed | _ -> TcMethodApplicationThen cenv env overallTy None tpenv None [] mExprAndTypeArgs mItem methodName ad NeverMutates false [(minfoAfterStaticArguments, None)] afterResolution NormalValUse [] ExprAtomicFlag.Atomic otherDelayed @@ -7828,7 +7938,7 @@ and TcItemThen cenv overallTy env tpenv (tinstEnclosing, item, mItem, rest, afte CallNameResolutionSink cenv.tcSink (mExprAndTypeArgs, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.eAccessRights) match otherDelayed with - | DelayedApp(atomicFlag, arg, mExprAndArg) :: otherDelayed -> + | DelayedApp(atomicFlag, _, arg, mExprAndArg) :: otherDelayed -> TcMethodApplicationThen cenv env overallTy None tpenv (Some tyargs) [] mExprAndArg mItem methodName ad NeverMutates false meths afterResolution NormalValUse [arg] atomicFlag otherDelayed | _ -> TcMethodApplicationThen cenv env overallTy None tpenv (Some tyargs) [] mExprAndTypeArgs mItem methodName ad NeverMutates false meths afterResolution NormalValUse [] ExprAtomicFlag.Atomic otherDelayed @@ -7846,12 +7956,12 @@ and TcItemThen cenv overallTy env tpenv (tinstEnclosing, item, mItem, rest, afte | minfo :: _ -> minfo.ApparentEnclosingType | [] -> error(Error(FSComp.SR.tcTypeHasNoAccessibleConstructor(), mItem)) match delayed with - | DelayedApp (_, arg, mExprAndArg) :: otherDelayed -> + | DelayedApp(_, _, arg, mExprAndArg) :: otherDelayed -> CallExprHasTypeSink cenv.tcSink (mExprAndArg, env.NameEnv, objTy, env.eAccessRights) TcCtorCall true cenv env tpenv overallTy objTy (Some mItem) item false [arg] mExprAndArg otherDelayed (Some afterResolution) - | DelayedTypeApp(tyargs, _mTypeArgs, mExprAndTypeArgs) :: DelayedApp (_, arg, mExprAndArg) :: otherDelayed -> + | DelayedTypeApp(tyargs, _mTypeArgs, mExprAndTypeArgs) :: DelayedApp(_, _, arg, mExprAndArg) :: otherDelayed -> let objTyAfterTyArgs, tpenv = TcNestedTypeApplication cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv mExprAndTypeArgs objTy tinstEnclosing tyargs CallExprHasTypeSink cenv.tcSink (mExprAndArg, env.NameEnv, objTyAfterTyArgs, env.eAccessRights) @@ -7953,8 +8063,8 @@ and TcItemThen cenv overallTy env tpenv (tinstEnclosing, item, mItem, rest, afte | SynExpr.While _ | SynExpr.For _ | SynExpr.ForEach _ - | SynExpr.ArrayOrListOfSeqExpr _ - | SynExpr.CompExpr _ + | SynExpr.ArrayOrListComputed _ + | SynExpr.ComputationExpr _ | SynExpr.Lambda _ | SynExpr.MatchLambda _ | SynExpr.Match _ @@ -7988,15 +8098,16 @@ and TcItemThen cenv overallTy env tpenv (tinstEnclosing, item, mItem, rest, afte | SynExpr.LetOrUseBang _ | SynExpr.DoBang _ | SynExpr.TraitCall _ + | SynExpr.IndexFromEnd _ + | SynExpr.IndexRange _ -> false - // Propagate the known application structure into function types Propagate cenv overallTy env tpenv (MakeApplicableExprNoFlex cenv expr) (tyOfExpr g expr) delayed // Take all simple arguments and process them before applying the constraint. let delayed1, delayed2 = - let pred = (function DelayedApp (_, arg, _) -> isSimpleArgument arg | _ -> false) + let pred = (function DelayedApp (_, _, arg, _) -> isSimpleArgument arg | _ -> false) List.takeWhile pred delayed, List.skipWhile pred delayed let intermediateTy = if isNil delayed2 then overallTy else NewInferenceType () @@ -8012,9 +8123,9 @@ and TcItemThen cenv overallTy env tpenv (tinstEnclosing, item, mItem, rest, afte | Item.DelegateCtor ty -> match delayed with - | DelayedApp (atomicFlag, arg, mItemAndArg) :: otherDelayed -> + | DelayedApp (atomicFlag, _, arg, mItemAndArg) :: otherDelayed -> TcNewDelegateThen cenv overallTy env tpenv mItem mItemAndArg ty arg atomicFlag otherDelayed - | DelayedTypeApp(tyargs, _mTypeArgs, mItemAndTypeArgs) :: DelayedApp (atomicFlag, arg, mItemAndArg) :: otherDelayed -> + | DelayedTypeApp(tyargs, _mTypeArgs, mItemAndTypeArgs) :: DelayedApp (atomicFlag, _, arg, mItemAndArg) :: otherDelayed -> let ty, tpenv = TcNestedTypeApplication cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv mItemAndTypeArgs ty tinstEnclosing tyargs // Report information about the whole expression including type arguments to VS @@ -8203,9 +8314,9 @@ and TcItemThen cenv overallTy env tpenv (tinstEnclosing, item, mItem, rest, afte and GetSynMemberApplicationArgs delayed tpenv = match delayed with - | DelayedApp (atomicFlag, arg, _) :: otherDelayed -> + | DelayedApp (atomicFlag, _, arg, _) :: otherDelayed -> atomicFlag, None, [arg], otherDelayed, tpenv - | DelayedTypeApp(tyargs, mTypeArgs, _) :: DelayedApp (atomicFlag, arg, _mExprAndArg) :: otherDelayed -> + | DelayedTypeApp(tyargs, mTypeArgs, _) :: DelayedApp (atomicFlag, _, arg, _mExprAndArg) :: otherDelayed -> (atomicFlag, Some (tyargs, mTypeArgs), [arg], otherDelayed, tpenv) | DelayedTypeApp(tyargs, mTypeArgs, _) :: otherDelayed -> (ExprAtomicFlag.Atomic, Some (tyargs, mTypeArgs), [], otherDelayed, tpenv) @@ -8507,7 +8618,7 @@ and TcMethodApplication let curriedCallerArgs, exprTy, delayed = match calledMeths with | [calledMeth] when not isProp && calledMeth.NumArgs.Length > 1 -> - [], NewInferenceType (), [ for x in curriedCallerArgs -> DelayedApp(ExprAtomicFlag.NonAtomic, x, x.Range) ] @ delayed + [], NewInferenceType (), [ for x in curriedCallerArgs -> DelayedApp(ExprAtomicFlag.NonAtomic, None, x, x.Range) ] @ delayed | _ when not isProp && calledMeths |> List.exists (fun calledMeth -> calledMeth.NumArgs.Length > 1) -> // This condition should only apply when multiple conflicting curried extension members are brought into scope error(Error(FSComp.SR.tcOverloadsCannotHaveCurriedArguments(), mMethExpr)) diff --git a/src/fsharp/CheckExpressions.fsi b/src/fsharp/CheckExpressions.fsi index 1b29c65a556..a8f4ffe950b 100644 --- a/src/fsharp/CheckExpressions.fsi +++ b/src/fsharp/CheckExpressions.fsi @@ -227,9 +227,9 @@ type TcFileState = isInternalTestSpanStackReferring: bool // forward call - TcSequenceExpressionEntry: TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> bool * bool ref * SynExpr -> range -> Expr * UnscopedTyparEnv + TcSequenceExpressionEntry: TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> bool * SynExpr -> range -> Expr * UnscopedTyparEnv // forward call - TcArrayOrListSequenceExpression: TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> bool * SynExpr -> range -> Expr * UnscopedTyparEnv + TcArrayOrListComputedExpression: TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> bool * SynExpr -> range -> Expr * UnscopedTyparEnv // forward call TcComputationExpression: TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> range * Expr * TType * SynExpr -> Expr * UnscopedTyparEnv } @@ -246,7 +246,7 @@ type TcFileState = tcVal: TcValF * isInternalTestSpanStackReferring: bool * // forward call to CheckComputationExpressions.fs - tcSequenceExpressionEntry: (TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> bool * bool ref * SynExpr -> range -> Expr * UnscopedTyparEnv) * + tcSequenceExpressionEntry: (TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> bool * SynExpr -> range -> Expr * UnscopedTyparEnv) * // forward call to CheckComputationExpressions.fs tcArrayOrListSequenceExpression: (TcFileState -> TcEnv -> TType -> UnscopedTyparEnv -> bool * SynExpr -> range -> Expr * UnscopedTyparEnv) * // forward call to CheckComputationExpressions.fs @@ -657,6 +657,10 @@ val TcConst: cenv: TcFileState -> ty: TType -> m: range -> env: TcEnv -> c: SynC /// Check a syntactic expression and convert it to a typed tree expression val TcExpr: cenv:TcFileState -> ty:TType -> env:TcEnv -> tpenv:UnscopedTyparEnv -> expr:SynExpr -> Expr * UnscopedTyparEnv +/// Converts 'a..b' to a call to the '(..)' operator in FSharp.Core +/// Converts 'a..b..c' to a call to the '(.. ..)' operator in FSharp.Core +val RewriteRangeExpr: expr: SynExpr -> SynExpr option + /// Check a syntactic expression and convert it to a typed tree expression val TcExprOfUnknownType: cenv:TcFileState -> env:TcEnv -> tpenv:UnscopedTyparEnv -> expr:SynExpr -> Expr * TType * UnscopedTyparEnv diff --git a/src/fsharp/CompilerDiagnostics.fs b/src/fsharp/CompilerDiagnostics.fs index 2006048da01..ea1dc03478d 100644 --- a/src/fsharp/CompilerDiagnostics.fs +++ b/src/fsharp/CompilerDiagnostics.fs @@ -374,8 +374,9 @@ let warningOn err level specificWarnOn = match n with | 1182 -> false // chkUnusedValue - off by default | 3180 -> false // abImplicitHeapAllocation - off by default + | 3366 -> false //tcIndexNotationDeprecated - currently off by default | 3517 -> false // optFailedToInlineSuggestedValue - off by default - | _ -> level >= GetWarningLevel err + | _ -> level >= GetWarningLevel err let SplitRelatedDiagnostics(err: PhasedDiagnostic) : PhasedDiagnostic * PhasedDiagnostic list = let ToPhased e = {Exception=e; Phase = err.Phase} @@ -1176,7 +1177,7 @@ let OutputPhasedErrorR (os: StringBuilder) (err: PhasedDiagnostic) (canSuggestNa let (|NONTERM_Category_Expr|_|) = function | Parser.NONTERM_argExpr|Parser.NONTERM_minusExpr|Parser.NONTERM_parenExpr|Parser.NONTERM_atomicExpr | Parser.NONTERM_appExpr|Parser.NONTERM_tupleExpr|Parser.NONTERM_declExpr|Parser.NONTERM_braceExpr|Parser.NONTERM_braceBarExpr - | Parser.NONTERM_typedSeqExprBlock + | Parser.NONTERM_typedSequentialExprBlock | Parser.NONTERM_interactiveExpr -> Some() | _ -> None diff --git a/src/fsharp/ErrorLogger.fs b/src/fsharp/ErrorLogger.fs index cb786b8d393..119a66621a6 100644 --- a/src/fsharp/ErrorLogger.fs +++ b/src/fsharp/ErrorLogger.fs @@ -385,6 +385,9 @@ module ErrorLoggerExtensions = member x.Warning exn = x.EmitDiagnostic (exn, FSharpDiagnosticSeverity.Warning) + member x.InformationalWarning exn = + x.EmitDiagnostic (exn, FSharpDiagnosticSeverity.Info) + member x.Error exn = x.ErrorR exn raise (ReportedError (Some exn)) @@ -465,6 +468,9 @@ let errorR exn = CompileThreadStatic.ErrorLogger.ErrorR exn /// Raises a warning with error recovery and returns unit. let warning exn = CompileThreadStatic.ErrorLogger.Warning exn +/// Raises a warning with error recovery and returns unit. +let informationalWarning exn = CompileThreadStatic.ErrorLogger.InformationalWarning exn + /// Raises a special exception and returns 'T - can be caught later at an errorRecovery point. let error exn = CompileThreadStatic.ErrorLogger.Error exn diff --git a/src/fsharp/ErrorLogger.fsi b/src/fsharp/ErrorLogger.fsi index d5fbb9d46e5..c550d99d85d 100644 --- a/src/fsharp/ErrorLogger.fsi +++ b/src/fsharp/ErrorLogger.fsi @@ -198,12 +198,18 @@ val SetThreadBuildPhaseNoUnwind: phase:BuildPhase -> unit val SetThreadErrorLoggerNoUnwind: errorLogger:ErrorLogger -> unit +/// Reports an error diagnostic and continues val errorR: exn:exn -> unit +/// Reports a warning diagnostic val warning: exn:exn -> unit +/// Reports an error and raises a ReportedError exception val error: exn:exn -> 'a +/// Reports an informational diagnostic +val informationalWarning: exn:exn -> unit + val simulateError: p:PhasedDiagnostic -> 'a val diagnosticSink: phasedError:PhasedDiagnostic * severity: FSharpDiagnosticSeverity -> unit diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 5b45a4451fb..5df81fb392f 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -594,7 +594,7 @@ tcExpressionWithIfRequiresParenthesis,"This list or array expression includes an 748,tcConstructRequiresComputationExpressions,"This construct may only be used within computation expressions. To return a value from an ordinary function simply write the expression without 'return'." 749,tcConstructRequiresSequenceOrComputations,"This construct may only be used within sequence or computation expressions" 750,tcConstructRequiresComputationExpression,"This construct may only be used within computation expressions" -751,tcInvalidIndexerExpression,"Invalid indexer expression" +751,tcInvalidIndexerExpression,"Incomplete expression or invalid use of indexer syntax" 752,tcObjectOfIndeterminateTypeUsedRequireTypeConstraint,"The operator 'expr.[idx]' has been used on an object of indeterminate type based on information prior to this program point. Consider adding further type constraints" 753,tcCannotInheritFromVariableType,"Cannot inherit from a variable type" 754,tcObjectConstructorsOnTypeParametersCannotTakeArguments,"Calls to object constructors on type parameters cannot be given arguments" @@ -1232,6 +1232,7 @@ invalidFullNameForProvidedType,"invalid full name for provided type" featureOverloadsForCustomOperations,"overloads for custom operations" featureExpandedMeasurables,"more types support units of measure" featurePrintfBinaryFormat,"binary formatting for integers" +featureIndexerNotationWithoutDot,"revised index and slicing notation" featureDiscardUseValue,"discard pattern in use binding" featureNonVariablePatternsToRightOfAsPatterns,"non-variable patterns to the right of 'as' patterns" featureAttributesToRightOfModuleKeyword,"attributes to the right of the 'module' keyword" @@ -1536,6 +1537,10 @@ featureStructActivePattern,"struct representation for active patterns" featureInterfacesWithMultipleGenericInstantiation,"interfaces with multiple generic instantiation" 3362,tcLiteralFieldAssignmentWithArg,"Cannot assign '%s' to a value marked literal" 3363,tcLiteralFieldAssignmentNoArg,"Cannot assign a value to another value marked literal" +3364,tcInvalidUseOfReverseIndex,"Invalid use of reverse index in list expression." +3365,tcHighPrecedenceFunctionApplicationToListDeprecated,"The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'." +3366,tcIndexNotationDeprecated,"The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code." +3367,tcHighPrecedenceFunctionApplicationToListReserved,"The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'." forFormatInvalidForInterpolated,"Interpolated strings may not use '%%' format specifiers unless each is given an expression, e.g. '%%d{{1+1}}'." forFormatInvalidForInterpolated2,".NET-style format specifiers such as '{{x,3}}' or '{{x:N5}}' may not be mixed with '%%' format specifiers." forFormatInvalidForInterpolated3,"The '%%P' specifier may not be used explicitly." diff --git a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index ab1c7adefad..cda7c06e099 100644 --- a/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/src/fsharp/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -408,7 +408,7 @@ ParserAndUntypedAST\lex.fsl - --module FSharp.Compiler.Parser --open FSharp.Compiler --open FSharp.Compiler.Syntax --internal --lexlib Internal.Utilities.Text.Lexing --parslib Internal.Utilities.Text.Parsing + -v --module FSharp.Compiler.Parser --open FSharp.Compiler --open FSharp.Compiler.Syntax --internal --lexlib Internal.Utilities.Text.Lexing --parslib Internal.Utilities.Text.Parsing ParserAndUntypedAST\pars.fsy diff --git a/src/fsharp/LanguageFeatures.fs b/src/fsharp/LanguageFeatures.fs index 85ef41d4ea4..9be3e219eb1 100644 --- a/src/fsharp/LanguageFeatures.fs +++ b/src/fsharp/LanguageFeatures.fs @@ -37,6 +37,7 @@ type LanguageFeature = | ExpandedMeasurables | StructActivePattern | PrintfBinaryFormat + | IndexerNotationWithoutDot | UseBindingValueDiscard | NonVariablePatternsToRightOfAsPatterns | AttributesToRightOfModuleKeyword @@ -84,6 +85,7 @@ type LanguageVersion (specifiedVersionAsString) = LanguageFeature.ResumableStateMachines, previewVersion LanguageFeature.StructActivePattern, previewVersion LanguageFeature.PrintfBinaryFormat, previewVersion + LanguageFeature.IndexerNotationWithoutDot, previewVersion LanguageFeature.UseBindingValueDiscard, previewVersion LanguageFeature.NonVariablePatternsToRightOfAsPatterns, previewVersion LanguageFeature.AttributesToRightOfModuleKeyword, previewVersion @@ -113,6 +115,14 @@ type LanguageVersion (specifiedVersionAsString) = | true, v -> v <= specified | false, _ -> false + /// Has preview been explicitly specified + member _.IsExplicitlySpecifiedAs50OrBefore() = + match specifiedVersionAsString with + | "4.6" -> true + | "4.7" -> true + | "5.0" -> true + | _ -> false + /// Has preview been explicitly specified member _.IsPreviewEnabled = specified = previewVersion @@ -163,6 +173,7 @@ type LanguageVersion (specifiedVersionAsString) = | LanguageFeature.ExpandedMeasurables -> FSComp.SR.featureExpandedMeasurables() | LanguageFeature.StructActivePattern -> FSComp.SR.featureStructActivePattern() | LanguageFeature.PrintfBinaryFormat -> FSComp.SR.featurePrintfBinaryFormat() + | LanguageFeature.IndexerNotationWithoutDot -> FSComp.SR.featureIndexerNotationWithoutDot() | LanguageFeature.UseBindingValueDiscard -> FSComp.SR.featureDiscardUseValue() | LanguageFeature.NonVariablePatternsToRightOfAsPatterns -> FSComp.SR.featureNonVariablePatternsToRightOfAsPatterns() | LanguageFeature.AttributesToRightOfModuleKeyword -> FSComp.SR.featureAttributesToRightOfModuleKeyword() diff --git a/src/fsharp/LanguageFeatures.fsi b/src/fsharp/LanguageFeatures.fsi index b7ee7c18f7a..17bae7a6d70 100644 --- a/src/fsharp/LanguageFeatures.fsi +++ b/src/fsharp/LanguageFeatures.fsi @@ -27,6 +27,7 @@ type LanguageFeature = | ExpandedMeasurables | StructActivePattern | PrintfBinaryFormat + | IndexerNotationWithoutDot | UseBindingValueDiscard | NonVariablePatternsToRightOfAsPatterns | AttributesToRightOfModuleKeyword @@ -43,6 +44,9 @@ type LanguageVersion = /// Has preview been explicitly specified member IsPreviewEnabled: bool + /// Has been explicitly specified as 4.6, 4.7 or 5.0 + member IsExplicitlySpecifiedAs50OrBefore: unit -> bool + /// Does the selected LanguageVersion support the specified feature member SupportsFeature: LanguageFeature -> bool diff --git a/src/fsharp/LexFilter.fs b/src/fsharp/LexFilter.fs index 1ecaab5c026..86d8ef70d0f 100644 --- a/src/fsharp/LexFilter.fs +++ b/src/fsharp/LexFilter.fs @@ -4,6 +4,7 @@ /// Implements the offside rule and a couple of other lexical transformations. module internal FSharp.Compiler.LexFilter +open System.Collections.Generic open Internal.Utilities.Text.Lexing open FSharp.Compiler open Internal.Utilities.Library @@ -430,7 +431,7 @@ type TokenTupPool() = let maxSize = 100 let mutable currentPoolSize = 0 - let stack = System.Collections.Generic.Stack(10) + let stack = Stack(10) member this.Rent() = if stack.Count = 0 then @@ -623,7 +624,7 @@ type LexFilterImpl (lightStatus: LightSyntaxStatus, compilingFsLib, lexer, lexbu // Fetch a raw token, either from the old lexer or from our delayedStack //-------------------------------------------------------------------------- - let delayedStack = System.Collections.Generic.Stack() + let delayedStack = Stack() let mutable tokensThatNeedNoProcessingCount = 0 let delayToken tokenTup = delayedStack.Push tokenTup @@ -684,6 +685,8 @@ type LexFilterImpl (lightStatus: LightSyntaxStatus, compilingFsLib, lexer, lexbu // Undentation rules //-------------------------------------------------------------------------- + //let indexerNotationWithoutDot = lexbuf.SupportsFeature LanguageFeature.IndexerNotationWithoutDot + let pushCtxt tokenTup (newCtxt: Context) = let rec undentationLimit strict stack = match newCtxt, stack with @@ -911,13 +914,17 @@ type LexFilterImpl (lightStatus: LightSyntaxStatus, compilingFsLib, lexer, lexbu let tokenEndPos = leftTokenTup.LexbufState.EndPos (tokenEndPos = lparenStartPos) - let nextTokenIsAdjacentLParenOrLBrack (tokenTup: TokenTup) = + let nextTokenIsAdjacentLBrack (tokenTup: TokenTup) = let lookaheadTokenTup = peekNextTokenTup() match lookaheadTokenTup.Token with - | LPAREN | LBRACK -> - if isAdjacent tokenTup lookaheadTokenTup then Some(lookaheadTokenTup.Token) else None - | _ -> - None + | LBRACK -> isAdjacent tokenTup lookaheadTokenTup + | _ -> false + + let nextTokenIsAdjacentLParen (tokenTup: TokenTup) = + let lookaheadTokenTup = peekNextTokenTup() + match lookaheadTokenTup.Token with + | LPAREN -> isAdjacent tokenTup lookaheadTokenTup + | _ -> false let nextTokenIsAdjacent firstTokenTup = let lookaheadTokenTup = peekNextTokenTup() @@ -955,7 +962,7 @@ type LexFilterImpl (lightStatus: LightSyntaxStatus, compilingFsLib, lexer, lexbu // On successful parse of a set of type parameters, look for an adjacent (, e.g. // M(args) // and insert a HIGH_PRECEDENCE_PAREN_APP - if not hasAfterOp && (match nextTokenIsAdjacentLParenOrLBrack lookaheadTokenTup with Some LPAREN -> true | _ -> false) then + if not hasAfterOp && nextTokenIsAdjacentLParen lookaheadTokenTup then let dotTokenTup = peekNextTokenTup() stack <- (pool.UseLocation(dotTokenTup, HIGH_PRECEDENCE_PAREN_APP), false) :: stack true @@ -969,7 +976,7 @@ type LexFilterImpl (lightStatus: LightSyntaxStatus, compilingFsLib, lexer, lexbu // On successful parse of a set of type parameters, look for an adjacent (, e.g. // M>(args) // and insert a HIGH_PRECEDENCE_PAREN_APP - if afterOp.IsNone && (match nextTokenIsAdjacentLParenOrLBrack lookaheadTokenTup with Some LPAREN -> true | _ -> false) then + if afterOp.IsNone && nextTokenIsAdjacentLParen lookaheadTokenTup then let dotTokenTup = peekNextTokenTup() stack <- (pool.UseLocation(dotTokenTup, HIGH_PRECEDENCE_PAREN_APP), false) :: stack true @@ -2243,6 +2250,20 @@ type LexFilterImpl (lightStatus: LightSyntaxStatus, compilingFsLib, lexer, lexbu | _ -> returnToken tokenLexbufState token + and insertHighPrecedenceApp (tokenTup: TokenTup) = + let dotTokenTup = peekNextTokenTup() + if debug then dprintf "inserting HIGH_PRECEDENCE_PAREN_APP at dotTokenPos = %a\n" outputPos (startPosOfTokenTup dotTokenTup) + let hpa = + if nextTokenIsAdjacentLParen tokenTup then + HIGH_PRECEDENCE_PAREN_APP + elif nextTokenIsAdjacentLBrack tokenTup then + HIGH_PRECEDENCE_BRACK_APP + else + failwith "unreachable" + delayToken(pool.UseLocation(dotTokenTup, hpa)) + delayToken tokenTup + true + and rulesForBothSoftWhiteAndHardWhite(tokenTup: TokenTup) = match tokenTup.Token with | HASH_IDENT ident -> @@ -2252,18 +2273,34 @@ type LexFilterImpl (lightStatus: LightSyntaxStatus, compilingFsLib, lexer, lexbu delayToken(TokenTup(HASH, hashPos, tokenTup.LastTokenPos)) true + //// Give a warning if '[' occurs immediately adjacent to non-identifier tokens that end an expression + //// + //// 3[3] + //// (f x)[3] + //// { X=1 }[3] + //// arr[3] + //// arr[3][3] + //// Only inserted if IndexerNotationWithoutDot is supported + //| IEEE64 _ | IEEE32 _ | DECIMAL _ | INT8 _ | INT16 _ | INT32 _ | INT64 _ | NATIVEINT _ | UINT8 _ | UINT16 _ | UINT32 _ | UINT64 _ | UNATIVEINT _ | BIGNUM _ + //| RBRACK | RBRACE _ | RPAREN when + // nextTokenIsAdjacentLBrack tokenTup -> + // //if indexerNotationWithoutDot then + // // insertHighPrecedenceApp tokenTup + // //else + // let nextTok = peekNextTokenTup() + // let m = mkSynRange (startPosOfTokenTup tokenTup) nextTok.EndPos + // warning(Error(FSComp.SR.tcIdentifierFollowedByLeftBracketReserved(), m)) + // false + + // Insert HIGH_PRECEDENCE_BRACK_APP if needed + // ident[3] + | IDENT _ when nextTokenIsAdjacentLBrack tokenTup -> + insertHighPrecedenceApp tokenTup + // Insert HIGH_PRECEDENCE_PAREN_APP if needed - | IDENT _ when (nextTokenIsAdjacentLParenOrLBrack tokenTup).IsSome -> - let dotTokenTup = peekNextTokenTup() - if debug then dprintf "inserting HIGH_PRECEDENCE_PAREN_APP at dotTokenPos = %a\n" outputPos (startPosOfTokenTup dotTokenTup) - let hpa = - match nextTokenIsAdjacentLParenOrLBrack tokenTup with - | Some LPAREN -> HIGH_PRECEDENCE_PAREN_APP - | Some LBRACK -> HIGH_PRECEDENCE_BRACK_APP - | _ -> failwith "unreachable" - delayToken(pool.UseLocation(dotTokenTup, hpa)) - delayToken tokenTup - true + // ident(3) + | IDENT _ when nextTokenIsAdjacentLParen tokenTup -> + insertHighPrecedenceApp tokenTup // Insert HIGH_PRECEDENCE_TYAPP if needed | DELEGATE | IDENT _ | IEEE64 _ | IEEE32 _ | DECIMAL _ | INT8 _ | INT16 _ | INT32 _ | INT64 _ | NATIVEINT _ | UINT8 _ | UINT16 _ | UINT32 _ | UINT64 _ | UNATIVEINT _ | BIGNUM _ when peekAdjacentTypars false tokenTup -> @@ -2404,7 +2441,7 @@ type LexFilter (lightStatus: LightSyntaxStatus, compilingFsLib, lexer, lexbuf: U // We don't interact with lexbuf state at all, any inserted tokens have same state/location as the real one read, so // we don't have to do any of the wrapped lexbuf magic that you see in LexFilterImpl. - let delayedStack = System.Collections.Generic.Stack() + let delayedStack = Stack() let delayToken tok = delayedStack.Push tok let popNextToken() = @@ -2422,18 +2459,16 @@ type LexFilter (lightStatus: LightSyntaxStatus, compilingFsLib, lexer, lexbuf: U member _.LexBuffer = inner.LexBuffer - member _.GetToken () = - let rec loop() = - let token = popNextToken() - match token with - | RBRACE _ -> - insertComingSoonTokens RBRACE_COMING_SOON RBRACE_IS_HERE - loop() - | RPAREN -> - insertComingSoonTokens RPAREN_COMING_SOON RPAREN_IS_HERE - loop() - | OBLOCKEND -> - insertComingSoonTokens OBLOCKEND_COMING_SOON OBLOCKEND_IS_HERE - loop() - | _ -> token - loop() + member lexer.GetToken () = + let token = popNextToken() + match token with + | RBRACE _ -> + insertComingSoonTokens RBRACE_COMING_SOON RBRACE_IS_HERE + lexer.GetToken() + | RPAREN -> + insertComingSoonTokens RPAREN_COMING_SOON RPAREN_IS_HERE + lexer.GetToken() + | OBLOCKEND -> + insertComingSoonTokens OBLOCKEND_COMING_SOON OBLOCKEND_IS_HERE + lexer.GetToken() + | _ -> token diff --git a/src/fsharp/LowerCallsAndSeqs.fs b/src/fsharp/LowerCallsAndSeqs.fs index 8d3fb8c288d..493dafc14cf 100644 --- a/src/fsharp/LowerCallsAndSeqs.fs +++ b/src/fsharp/LowerCallsAndSeqs.fs @@ -1009,7 +1009,7 @@ let (|OptionalCoerce|) expr = | Expr.Op (TOp.Coerce, _, [arg], _) -> arg | _ -> expr -// Making 'seq' optional means this kicks in for FSharp.Core, see TcArrayOrListSequenceExpression +// Making 'seq' optional means this kicks in for FSharp.Core, see TcArrayOrListComputedExpression // which only adds a 'seq' call outside of FSharp.Core let (|OptionalSeq|_|) g amap expr = match expr with diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index 23d46cd3d05..6bbf976f3c8 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -530,14 +530,25 @@ type SynExpr = bodyExpr: SynExpr * range: range - | ArrayOrListOfSeqExpr of + | ArrayOrListComputed of isArray: bool * expr: SynExpr * range: range - | CompExpr of - isArrayOrList: bool * - isNotNakedRefCell: bool ref * + | IndexRange of + expr1: SynExpr option * + opm: range * + expr2: SynExpr option* + range1: range * + range2: range * + range: range + + | IndexFromEnd of + expr: SynExpr * + range: range + + | ComputationExpr of + hasSeqBuilder: bool * expr: SynExpr * range: range @@ -666,13 +677,13 @@ type SynExpr = | DotIndexedGet of objectExpr: SynExpr * - indexExprs: SynIndexerArg list * + indexArgs: SynExpr * dotRange: range * range: range | DotIndexedSet of objectExpr: SynExpr * - indexExprs: SynIndexerArg list * + indexArgs: SynExpr * valueExpr: SynExpr * leftOfSetRange: range * dotRange: range * @@ -840,8 +851,8 @@ type SynExpr = | SynExpr.While (range=m) | SynExpr.For (range=m) | SynExpr.ForEach (range=m) - | SynExpr.CompExpr (range=m) - | SynExpr.ArrayOrListOfSeqExpr (range=m) + | SynExpr.ComputationExpr (range=m) + | SynExpr.ArrayOrListComputed (range=m) | SynExpr.Lambda (range=m) | SynExpr.Match (range=m) | SynExpr.MatchLambda (range=m) @@ -871,6 +882,8 @@ type SynExpr = | SynExpr.LibraryOnlyUnionCaseFieldSet (range=m) | SynExpr.LibraryOnlyILAssembly (range=m) | SynExpr.LibraryOnlyStaticOptimization (range=m) + | SynExpr.IndexRange (range=m) + | SynExpr.IndexFromEnd (range=m) | SynExpr.TypeTest (range=m) | SynExpr.Upcast (range=m) | SynExpr.AddressOf (range=m) @@ -926,24 +939,6 @@ type SynInterpolatedStringPart = | String of value: string * range: range | FillExpr of fillExpr: SynExpr * qualifiers: Ident option -[] -type SynIndexerArg = - | Two of - expr1: SynExpr * - fromEnd1: bool * - expr2: SynExpr * - fromEnd2: bool * - range1: range * - range2: range - - | One of - expr: SynExpr * - fromEnd: bool * range - - member x.Range = match x with Two (e1, _, e2, _, _, _) -> unionRanges e1.Range e2.Range | One (e, _, _) -> e.Range - - member x.Exprs = match x with Two (e1, _, e2, _, _, _) -> [e1;e2] | One (e, _, _) -> [e] - [] type SynSimplePat = | Id of diff --git a/src/fsharp/SyntaxTree.fsi b/src/fsharp/SyntaxTree.fsi index 035f3d9b42d..23caef54dd9 100644 --- a/src/fsharp/SyntaxTree.fsi +++ b/src/fsharp/SyntaxTree.fsi @@ -643,15 +643,33 @@ type SynExpr = range: range /// F# syntax: [ expr ], [| expr |] - | ArrayOrListOfSeqExpr of + | ArrayOrListComputed of isArray: bool * expr: SynExpr * range: range + /// F# syntax: expr.. + /// F# syntax: ..expr + /// F# syntax: expr..expr + /// F# syntax: * + /// A two-element range indexer argument a..b, a.., ..b. Also used to represent + /// a range in a list, array or sequence expression. + | IndexRange of + expr1: SynExpr option * + opm: range * + expr2: SynExpr option* + range1: range * + range2: range * + range: range + + /// F# syntax: ^expr + | IndexFromEnd of + expr: SynExpr * + range: range + /// F# syntax: { expr } - | CompExpr of - isArrayOrList: bool * - isNotNakedRefCell: bool ref * + | ComputationExpr of + hasSeqBuilder: bool * expr: SynExpr * range: range @@ -820,14 +838,14 @@ type SynExpr = /// F# syntax: expr.[expr, ..., expr] | DotIndexedGet of objectExpr: SynExpr * - indexExprs: SynIndexerArg list * + indexArgs: SynExpr * dotRange: range * range: range /// F# syntax: expr.[expr, ..., expr] <- expr | DotIndexedSet of objectExpr: SynExpr * - indexExprs: SynIndexerArg list * + indexArgs: SynExpr * valueExpr: SynExpr * leftOfSetRange: range * dotRange: range * @@ -1031,29 +1049,6 @@ type SynInterpolatedStringPart = | String of value: string * range: range | FillExpr of fillExpr: SynExpr * qualifiers: Ident option -/// Represents a syntax tree for an F# indexer expression argument -[] -type SynIndexerArg = - /// A two-element range indexer argument - | Two of - expr1: SynExpr * - fromEnd1: bool * - expr2: SynExpr * - fromEnd2: bool * - range1: range * - range2: range - - /// A one-element item indexer argument - | One of - expr: SynExpr * - fromEnd: bool * range - - /// Gets the syntax range of this construct - member Range: range - - /// Get the one or two expressions as a list - member Exprs: SynExpr list - /// Represents a syntax tree for simple F# patterns [] type SynSimplePat = diff --git a/src/fsharp/SyntaxTreeOps.fs b/src/fsharp/SyntaxTreeOps.fs index 5c1f0ce6baa..6fe75f5f99e 100644 --- a/src/fsharp/SyntaxTreeOps.fs +++ b/src/fsharp/SyntaxTreeOps.fs @@ -77,7 +77,7 @@ let rec IsControlFlowExpression e = | SynExpr.LetOrUse _ | SynExpr.Sequential _ // Treat "ident { ... }" as a control flow expression - | SynExpr.App (_, _, SynExpr.Ident _, SynExpr.CompExpr _, _) + | SynExpr.App (_, _, SynExpr.Ident _, SynExpr.ComputationExpr _, _) | SynExpr.IfThenElse _ | SynExpr.LetOrUseBang _ | SynExpr.Match _ @@ -303,14 +303,14 @@ let mkSynApp5 f x1 x2 x3 x4 x5 m = mkSynApp1 (mkSynApp4 f x1 x2 x3 x4 m) x5 m let mkSynDotParenSet m a b c = mkSynTrifix m parenSet a b c -let mkSynDotBrackGet m mDot a b fromEnd = SynExpr.DotIndexedGet (a, [SynIndexerArg.One (b, fromEnd, m)], mDot, m) +let mkSynDotBrackGet m mDot a b = SynExpr.DotIndexedGet (a, b, mDot, m) let mkSynQMarkSet m a b c = mkSynTrifix m qmarkSet a b c -let mkSynDotBrackSliceGet m mDot arr sliceArg = SynExpr.DotIndexedGet (arr, [sliceArg], mDot, m) +//let mkSynDotBrackSliceGet m mDot arr sliceArg = SynExpr.DotIndexedGet (arr, [sliceArg], mDot, m) -let mkSynDotBrackSeqSliceGet m mDot arr (argsList: list) = - SynExpr.DotIndexedGet (arr, argsList, mDot, m) +//let mkSynDotBrackSeqSliceGet m mDot arr (argsList: list) = +// SynExpr.DotIndexedGet (arr, argsList, mDot, m) let mkSynDotParenGet lhsm dotm a b = match b with @@ -650,8 +650,8 @@ let rec synExprContainsError inpExpr = | SynExpr.TypeTest (e, _, _) | SynExpr.Upcast (e, _, _) | SynExpr.AddressOf (_, e, _, _) - | SynExpr.CompExpr (_, _, e, _) - | SynExpr.ArrayOrListOfSeqExpr (_, e, _) + | SynExpr.ComputationExpr (_, e, _) + | SynExpr.ArrayOrListComputed (_, e, _) | SynExpr.Typed (e, _, _) | SynExpr.FromParseError (e, _) | SynExpr.Do (e, _) @@ -731,11 +731,18 @@ let rec synExprContainsError inpExpr = | SynExpr.IfThenElse (_, _, e1, _, e2, _, e3opt, _, _, _, _) -> walkExpr e1 || walkExpr e2 || walkExprOpt e3opt - | SynExpr.DotIndexedGet (e1, es, _, _) -> - walkExpr e1 || walkExprs [ for e in es do yield! e.Exprs ] + | SynExpr.IndexRange (expr1, _, expr2, _, _, _) -> + (match expr1 with Some e -> walkExpr e | None -> false) || + (match expr2 with Some e -> walkExpr e | None -> false) - | SynExpr.DotIndexedSet (e1, es, e2, _, _, _) -> - walkExpr e1 || walkExprs [ for e in es do yield! e.Exprs ] || walkExpr e2 + | SynExpr.IndexFromEnd (e, _) -> + walkExpr e + + | SynExpr.DotIndexedGet (e1, indexArgs, _, _) -> + walkExpr e1 || walkExpr indexArgs + + | SynExpr.DotIndexedSet (e1, indexArgs, e2, _, _, _) -> + walkExpr e1 || walkExpr indexArgs || walkExpr e2 | SynExpr.DotNamedIndexedPropertySet (e1, _, e2, e3, _) -> walkExpr e1 || walkExpr e2 || walkExpr e3 diff --git a/src/fsharp/SyntaxTreeOps.fsi b/src/fsharp/SyntaxTreeOps.fsi index 2d7fd843011..d40cdcb351e 100644 --- a/src/fsharp/SyntaxTreeOps.fsi +++ b/src/fsharp/SyntaxTreeOps.fsi @@ -119,13 +119,13 @@ val mkSynApp5: f:SynExpr -> x1:SynExpr -> x2:SynExpr -> x3:SynExpr -> x4:SynExpr val mkSynDotParenSet: m:range -> a:SynExpr -> b:SynExpr -> c:SynExpr -> SynExpr -val mkSynDotBrackGet: m:range -> mDot:range -> a:SynExpr -> b:SynExpr -> fromEnd:bool -> SynExpr +val mkSynDotBrackGet: m:range -> mDot:range -> a:SynExpr -> b:SynExpr -> SynExpr val mkSynQMarkSet: m:range -> a:SynExpr -> b:SynExpr -> c:SynExpr -> SynExpr -val mkSynDotBrackSliceGet: m:range -> mDot:range -> arr:SynExpr -> sliceArg:SynIndexerArg -> SynExpr +//val mkSynDotBrackSliceGet: m:range -> mDot:range -> arr:SynExpr -> sliceArg:SynIndexerArg -> SynExpr -val mkSynDotBrackSeqSliceGet: m:range -> mDot:range -> arr:SynExpr -> argsList:SynIndexerArg list -> SynExpr +//val mkSynDotBrackSeqSliceGet: m:range -> mDot:range -> arr:SynExpr -> argsList:SynIndexerArg list -> SynExpr val mkSynDotParenGet: lhsm:range -> dotm:range -> a:SynExpr -> b:SynExpr -> SynExpr diff --git a/src/fsharp/fsi/fsi.fs b/src/fsharp/fsi/fsi.fs index f7ee5973099..6e131306bae 100644 --- a/src/fsharp/fsi/fsi.fs +++ b/src/fsharp/fsi/fsi.fs @@ -2400,7 +2400,7 @@ type internal FsiInteractionProcessor let parseExpression (tokenizer:LexFilter.LexFilter) = reusingLexbufForParsing tokenizer.LexBuffer (fun () -> - Parser.typedSeqExprEOF (fun _ -> tokenizer.GetToken()) tokenizer.LexBuffer) + Parser.typedSequentialExprEOF (fun _ -> tokenizer.GetToken()) tokenizer.LexBuffer) let mainThreadProcessParsedExpression ctok errorLogger (expr, istate) = istate |> InteractiveCatch errorLogger (fun istate -> diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index d1519188df4..c22538bfaec 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -38,12 +38,6 @@ let exprFromParseError (e:SynExpr) = SynExpr.FromParseError (e, e.Range) let patFromParseError (e:SynPat) = SynPat.FromParseError(e, e.Range) -let mkSynOptionalExpr (m: range) xopt = - let m = m.MakeSynthetic() - match xopt with - | None -> mkSynLidGet m FSharpLib.CorePath "None" - | Some x -> SynExpr.App (ExprAtomicFlag.NonAtomic, false, mkSynLidGet m FSharpLib.CorePath "Some", x, m) - // record bindings returned by the recdExprBindings rule has shape: // (binding, separator-before-this-binding) // this function converts arguments from form @@ -314,8 +308,8 @@ let rangeOfLongIdent(lid:LongIdent) = %token COMMENT WHITESPACE HASH_LINE HASH_LIGHT INACTIVECODE LINE_COMMENT STRING_TEXT EOF %token HASH_IF HASH_ELSE HASH_ENDIF -%start signatureFile implementationFile interaction typedSeqExprEOF typEOF -%type typedSeqExprEOF +%start signatureFile implementationFile interaction typedSequentialExprEOF typEOF +%type typedSequentialExprEOF %type implementationFile %type signatureFile %type interaction @@ -330,7 +324,7 @@ let rangeOfLongIdent(lid:LongIdent) = %type declExprBlock %type headBindingPattern %type atomicExprAfterType -%type typedSeqExprBlock +%type typedSequentialExprBlock %type atomicExpr %type tyconDefnOrSpfnSimpleRepr %type <(SynEnumCase, SynUnionCase) Choice list> unionTypeRepr @@ -496,10 +490,9 @@ let rangeOfLongIdent(lid:LongIdent) = %right COLON_EQUALS %nonassoc pat_tuple expr_tuple %left COMMA -%nonassoc slice_expr /* matrix.[e COMMA e] has higher precedence than "e COMMA e" */ +%nonassoc open_range_expr +%left DOT_DOT /* for matrix.[1..2, 3..4] the ".." has higher precedence than expression "2 COMMA 3" */ %nonassoc interpolation_fill /* "...{3,N4}..." .NET style fill has higher precedence than "e COMMA e" */ -%nonassoc DOT_DOT /* for matrix.[1..2, 3..4] the ".." has higher precedence than expression "2 COMMA 3" */ -%nonassoc slice_comma /* for matrix.[1..2, 3..4] the ", " has higher precedence than ".." */ %nonassoc paren_pat_colon %nonassoc paren_pat_attribs %left OR BAR_BAR JOIN_IN @@ -1712,7 +1705,7 @@ classDefnMemberGetSetElements: { [$1;$3] } classDefnMemberGetSetElement: - | opt_inline opt_attributes bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSeqExprBlock + | opt_inline opt_attributes bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSequentialExprBlock { let mRhs = ($6 : SynExpr).Range ($1, $2, $3, $4, $6, mRhs) } @@ -1720,7 +1713,7 @@ classDefnMemberGetSetElement: /* The core of a member definition */ memberCore: /* Methods and simple getter properties */ - | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSeqExprBlock + | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSequentialExprBlock { let mRhs = $5.Range let optReturnType = $3 let bindingBuilder, mBindLhs = $2 @@ -1987,7 +1980,7 @@ classDefnMember: let isStatic, flags = $3 $4 $1 isStatic flags rangeStart } - | opt_attributes opt_declVisibility NEW atomicPattern optAsSpec EQUALS typedSeqExprBlock opt_ODECLEND + | opt_attributes opt_declVisibility NEW atomicPattern optAsSpec EQUALS typedSequentialExprBlock opt_ODECLEND { let mWholeBindLhs = rhs2 parseState 1 (if Option.isSome $5 then 5 else 4) let m = unionRanges mWholeBindLhs $7.Range let expr = $7 @@ -2017,7 +2010,7 @@ valDefnDecl: /* An auto-property definition in an object type definition */ autoPropsDefnDecl: - | VAL opt_mutable opt_access ident opt_typ EQUALS typedSeqExprBlock classMemberSpfnGetSet + | VAL opt_mutable opt_access ident opt_typ EQUALS typedSequentialExprBlock classMemberSpfnGetSet { let doc = grabXmlDoc(parseState, 5) let mGetSetOpt, getSet = $8 if $2 then @@ -2614,7 +2607,7 @@ defnBindings: /* A 'do ...' statement in the non-#light syntax */ doBinding: - | DO typedSeqExprBlock + | DO typedSequentialExprBlock { let mDoKwd = rhs parseState 1 let mWhole = unionRanges mDoKwd $2.Range // any attributes prior to the 'let' are left free, e.g. become top-level attributes @@ -2650,7 +2643,7 @@ hardwhiteLetBindings: /* A 'do ...' statement */ hardwhiteDoBinding: - | ODO typedSeqExprBlock hardwhiteDefnBindingsTerminator + | ODO typedSequentialExprBlock hardwhiteDefnBindingsTerminator { let mLetKwd = rhs parseState 1 let bindingSetRange = unionRanges mLetKwd $2.Range let seqPt = DebugPointAtBinding.NoneAtDo @@ -2868,7 +2861,7 @@ typedExprWithStaticOptimizationsBlock: { $1 } typedExprWithStaticOptimizations : - | typedSeqExpr opt_staticOptimizations + | typedSequentialExpr opt_staticOptimizations { $1, List.rev $2 } opt_staticOptimizations: @@ -2879,7 +2872,7 @@ opt_staticOptimizations: { [] } staticOptimization: - | WHEN staticOptimizationConditions EQUALS typedSeqExprBlock + | WHEN staticOptimizationConditions EQUALS typedSequentialExprBlock { ($2, $4) } staticOptimizationConditions: @@ -3313,20 +3306,20 @@ listPatternElements: { $1 :: $3 } /* The lexfilter likes to insert OBLOCKBEGIN/OBLOCKEND pairs */ -typedSeqExprBlock: - | OBLOCKBEGIN typedSeqExpr oblockend +typedSequentialExprBlock: + | OBLOCKBEGIN typedSequentialExpr oblockend { $2 } - | OBLOCKBEGIN typedSeqExpr recover + | OBLOCKBEGIN typedSequentialExpr recover { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFileExpression()) exprFromParseError $2 } - | typedSeqExpr + | typedSequentialExpr { $1 } /* The lexfilter likes to insert OBLOCKBEGIN/OBLOCKEND pairs */ declExprBlock: - | OBLOCKBEGIN typedSeqExpr oblockend + | OBLOCKBEGIN typedSequentialExpr oblockend { $2 } | declExpr @@ -3334,26 +3327,26 @@ declExprBlock: /* For some constructs the lex filter can't be sure to insert a matching OBLOCKEND, e.g. "function a -> b | c -> d" all in one line */ /* for these it only inserts a trailing ORIGHT_BLOCK_END */ -typedSeqExprBlockR: - | typedSeqExpr ORIGHT_BLOCK_END +typedSequentialExprBlockR: + | typedSequentialExpr ORIGHT_BLOCK_END { $1 } - | typedSeqExpr + | typedSequentialExpr { $1 } -typedSeqExpr: - | seqExpr COLON typeWithTypeConstraints +typedSequentialExpr: + | sequentialExpr COLON typeWithTypeConstraints { SynExpr.Typed ($1, $3, unionRanges $1.Range $3.Range) } - | seqExpr + | sequentialExpr { $1 } -typedSeqExprEOF: - | typedSeqExpr EOF +typedSequentialExprEOF: + | typedSequentialExpr EOF { checkEndOfFileError $2; $1 } -seqExpr: - | declExpr seps seqExpr +sequentialExpr: + | declExpr seps sequentialExpr { SynExpr.Sequential (DebugPointAtSequential.SuppressNeither, true, $1, $3, unionRanges $1.Range $3.Range) } | declExpr seps @@ -3362,10 +3355,10 @@ seqExpr: | declExpr %prec SEMICOLON { $1 } - | declExpr THEN seqExpr %prec prec_then_before + | declExpr THEN sequentialExpr %prec prec_then_before { SynExpr.Sequential (DebugPointAtSequential.SuppressNeither, false, $1, $3, unionRanges $1.Range $3.Range ) } - | declExpr OTHEN OBLOCKBEGIN typedSeqExpr oblockend %prec prec_then_before + | declExpr OTHEN OBLOCKBEGIN typedSequentialExpr oblockend %prec prec_then_before { SynExpr.Sequential (DebugPointAtSequential.SuppressNeither, false, $1, $4, unionRanges $1.Range $4.Range) } | hardwhiteLetBindings %prec prec_args_error @@ -3388,12 +3381,12 @@ recover: { debugPrint("recovering via EOF"); false } moreBinders: - | AND_BANG headBindingPattern EQUALS typedSeqExprBlock IN moreBinders %prec expr_let + | AND_BANG headBindingPattern EQUALS typedSequentialExprBlock IN moreBinders %prec expr_let { let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) let m = rhs parseState 1 (* TODO Pretty sure this is wrong *) (spBind, $1, true, $2, $4, m) :: $6 } - | OAND_BANG headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders %prec expr_let + | OAND_BANG headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders %prec expr_let { $5 "and!" (rhs parseState 1) // report unterminated error let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) (* TODO Pretty sure this is wrong *) let m = rhs parseState 1 (* TODO Pretty sure this is wrong *) @@ -3403,7 +3396,7 @@ moreBinders: { [] } declExpr: - | defnBindings IN typedSeqExpr %prec expr_let + | defnBindings IN typedSequentialExpr %prec expr_let { mkLocalBindings (unionRanges (rhs2 parseState 1 2) $3.Range, $1, $3) } | defnBindings IN error %prec expr_let @@ -3412,7 +3405,7 @@ declExpr: FSComp.SR.parsNoMatchingInForLet() -- leave this in for now - it's an unused error string */ - | hardwhiteLetBindings typedSeqExprBlock %prec expr_let + | hardwhiteLetBindings typedSequentialExprBlock %prec expr_let { let hwlb, m = $1 mkLocalBindings (unionRanges m $2.Range, hwlb, $2) } @@ -3421,7 +3414,7 @@ declExpr: reportParseErrorAt (match hwlb with (BindingSetPreAttrs(m, _, _, _, _)) -> m) (FSComp.SR.parsErrorInReturnForLetIncorrectIndentation()) mkLocalBindings (m, hwlb, arbExpr("declExpr2", (rhs parseState 2))) } - | hardwhiteLetBindings OBLOCKSEP typedSeqExprBlock %prec expr_let + | hardwhiteLetBindings OBLOCKSEP typedSequentialExprBlock %prec expr_let { let hwlb, m = $1 mkLocalBindings (unionRanges m $3.Range, hwlb, $3) } @@ -3440,29 +3433,29 @@ declExpr: | anonLambdaExpr %prec expr_fun { $1 } - | MATCH typedSeqExpr withClauses %prec expr_match + | MATCH typedSequentialExpr withClauses %prec expr_match { let mMatch = (rhs parseState 1) let mWith, (clauses, mLast) = $3 let spBind = DebugPointAtBinding.Yes(unionRanges mMatch mWith) SynExpr.Match (spBind, $2, clauses, unionRanges mMatch mLast) } - | MATCH typedSeqExpr recover %prec expr_match + | MATCH typedSequentialExpr recover %prec expr_match { if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileMatch()) // Produce approximate expression during error recovery exprFromParseError $2 } - | MATCH_BANG typedSeqExpr withClauses %prec expr_match + | MATCH_BANG typedSequentialExpr withClauses %prec expr_match { let mMatch = (rhs parseState 1) let mWith, (clauses, mLast) = $3 let spBind = DebugPointAtBinding.Yes(unionRanges mMatch mWith) SynExpr.MatchBang (spBind, $2, clauses, unionRanges mMatch mLast) } - | MATCH_BANG typedSeqExpr recover %prec expr_match + | MATCH_BANG typedSequentialExpr recover %prec expr_match { if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileMatch()) // Produce approximate expression during error recovery exprFromParseError $2 } - | TRY typedSeqExprBlockR withClauses %prec expr_try + | TRY typedSequentialExprBlockR withClauses %prec expr_try { let mTry = (rhs parseState 1) let spTry = DebugPointAtTry.Yes mTry let mWith, (clauses, mLast) = $3 @@ -3472,13 +3465,13 @@ declExpr: let mTryToLast = unionRanges mTry mLast SynExpr.TryWith ($2, mTryToWith, clauses, mWithToLast, mTryToLast, spTry, spWith) } - | TRY typedSeqExprBlockR recover %prec expr_try + | TRY typedSequentialExprBlockR recover %prec expr_try { // Produce approximate expression during error recovery // Include any expressions to make sure they gets type checked in case that generates useful results for intellisense if not $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileTry()) exprFromParseError $2 } - | TRY typedSeqExprBlockR FINALLY typedSeqExprBlock %prec expr_try + | TRY typedSequentialExprBlockR FINALLY typedSequentialExprBlock %prec expr_try { let mTry = rhs parseState 1 let spTry = DebugPointAtTry.Yes mTry let spFinally = DebugPointAtFinally.Yes (rhs parseState 3) @@ -3524,13 +3517,13 @@ declExpr: | OASSERT %prec expr_assert { raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsAssertIsNotFirstClassValue()) } - | WHILE declExpr doToken typedSeqExprBlock doneDeclEnd + | WHILE declExpr doToken typedSequentialExprBlock doneDeclEnd { let mWhileHeader = unionRanges (rhs parseState 1) $2.Range let spWhile = DebugPointAtWhile.Yes mWhileHeader let mWhileAll = unionRanges (rhs parseState 1) $4.Range SynExpr.While (spWhile, $2, $4, mWhileAll) } - | WHILE declExpr doToken typedSeqExprBlock recover + | WHILE declExpr doToken typedSequentialExprBlock recover { if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileWhile()) let mWhileHeader = unionRanges (rhs parseState 1) $2.Range let spWhile = DebugPointAtWhile.Yes mWhileHeader @@ -3565,13 +3558,13 @@ declExpr: let mWhileAll = unionRanges (rhs parseState 1) (rhs parseState 3) exprFromParseError (SynExpr.While (spWhile, arbExpr("whileGuard1", mWhileHeader), arbExpr("whileBody3", mWhileBodyArb), mWhileAll)) } - | FOR forLoopBinder doToken typedSeqExprBlock doneDeclEnd + | FOR forLoopBinder doToken typedSequentialExprBlock doneDeclEnd { let mForLoopHeader = rhs2 parseState 1 3 let spBind = DebugPointAtFor.Yes mForLoopHeader let (a, b, _) = $2 SynExpr.ForEach (spBind, SeqExprOnly false, true, a, b, $4, unionRanges (rhs parseState 1) $4.Range) } - | FOR forLoopBinder doToken typedSeqExprBlock ends_coming_soon_or_recover + | FOR forLoopBinder doToken typedSequentialExprBlock ends_coming_soon_or_recover { if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor()) let mForLoopHeader = rhs2 parseState 1 3 let spBind = DebugPointAtFor.Yes mForLoopHeader @@ -3606,14 +3599,14 @@ declExpr: let mForLoopAll = rhs2 parseState 1 3 SynExpr.ForEach (spBind, SeqExprOnly false, true, a, b, arbExpr("forLoopBody1", mForLoopBodyArb), mForLoopAll) } - | FOR forLoopRange doToken typedSeqExprBlock doneDeclEnd + | FOR forLoopRange doToken typedSequentialExprBlock doneDeclEnd { let mForLoopHeader = rhs2 parseState 1 3 let spBind = DebugPointAtFor.Yes mForLoopHeader let (a, b, c, d) = $2 let mForLoopAll = unionRanges (rhs parseState 1) $4.Range SynExpr.For (spBind, a, b, c, d, $4, mForLoopAll) } - | FOR forLoopRange doToken typedSeqExprBlock recover + | FOR forLoopRange doToken typedSequentialExprBlock recover { if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFor()) // Still produce an expression let mForLoopHeader = rhs2 parseState 1 3 @@ -3650,7 +3643,7 @@ declExpr: exprFromParseError (SynExpr.For (spBind, a, b, c, d, arbExpr("declExpr11", mForLoopBodyArb), mForLoopAll)) } - | FOR error doToken typedSeqExprBlock doneDeclEnd + | FOR error doToken typedSequentialExprBlock doneDeclEnd { // silent recovery let mForLoopHeader = rhs2 parseState 1 2 let mForLoopAll = unionRanges (rhs parseState 1) $4.Range @@ -3691,29 +3684,29 @@ declExpr: { let mYieldAll = rhs parseState 1 SynExpr.YieldOrReturnFrom (($1, not $1), arbExpr("yield!", mYieldAll), mYieldAll) } - | BINDER headBindingPattern EQUALS typedSeqExprBlock IN opt_OBLOCKSEP moreBinders typedSeqExprBlock %prec expr_let + | BINDER headBindingPattern EQUALS typedSequentialExprBlock IN opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let { let spBind = DebugPointAtBinding.Yes(rhs2 parseState 1 5) let m = unionRanges (rhs parseState 1) $8.Range SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m) } - | OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders typedSeqExprBlock %prec expr_let + | OBINDER headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP moreBinders typedSequentialExprBlock %prec expr_let { $5 (if $1 = "use" then "use!" else "let!") (rhs parseState 1) // report unterminated error let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) let m = unionRanges (rhs parseState 1) $8.Range SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, $7, $8, m) } - | OBINDER headBindingPattern EQUALS typedSeqExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let + | OBINDER headBindingPattern EQUALS typedSequentialExprBlock hardwhiteDefnBindingsTerminator opt_OBLOCKSEP error %prec expr_let { // error recovery that allows intellisense when writing incomplete computation expressions let spBind = DebugPointAtBinding.Yes(unionRanges (rhs parseState 1) $4.Range) let mAll = unionRanges (rhs parseState 1) (rhs parseState 7) let m = $4.Range.EndRange // zero-width range SynExpr.LetOrUseBang(spBind, ($1 = "use"), true, $2, $4, [], SynExpr.ImplicitZero m, mAll) } - | DO_BANG typedSeqExpr IN opt_OBLOCKSEP typedSeqExprBlock %prec expr_let + | DO_BANG typedSequentialExpr IN opt_OBLOCKSEP typedSequentialExprBlock %prec expr_let { let spBind = DebugPointAtBinding.NoneAtDo SynExpr.LetOrUseBang(spBind, false, true, SynPat.Const(SynConst.Unit, $2.Range), $2, [], $5, unionRanges (rhs parseState 1) $5.Range) } - | ODO_BANG typedSeqExprBlock hardwhiteDefnBindingsTerminator %prec expr_let + | ODO_BANG typedSequentialExprBlock hardwhiteDefnBindingsTerminator %prec expr_let { SynExpr.DoBang ($2, unionRanges (rhs parseState 1) $2.Range) } | FOR forLoopBinder opt_OBLOCKSEP arrowThenExprR %prec expr_let @@ -3723,7 +3716,7 @@ declExpr: | FIXED declExpr { SynExpr.Fixed ($2, (unionRanges (rhs parseState 1) $2.Range)) } - | RARROW typedSeqExprBlockR + | RARROW typedSequentialExprBlockR { errorR(Error(FSComp.SR.parsArrowUseIsLimited(), lhs parseState)) SynExpr.YieldOrReturn ((true, true), $2, (unionRanges (rhs parseState 1) $2.Range)) } @@ -3892,6 +3885,32 @@ declExpr: { reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnfinishedExpression($2)) exprFromParseError(mkSynInfix (rhs parseState 2) $1 $2 (arbExpr("declExprInfix", (rhs parseState 3).StartRange))) } + | declExpr DOT_DOT declExpr + { let wholem = rhs2 parseState 1 3 + let opm = rhs parseState 2 + SynExpr.IndexRange(Some $1, opm, Some $3, rhs parseState 1, rhs parseState 3, wholem) } + + | declExpr DOT_DOT %prec open_range_expr + { let wholem = rhs2 parseState 1 2 + let opm = rhs parseState 2 + SynExpr.IndexRange(Some $1, opm, None, rhs parseState 1, opm, wholem) } + + | DOT_DOT declExpr %prec open_range_expr + { let wholem = rhs2 parseState 1 2 + let opm = rhs parseState 1 + SynExpr.IndexRange(None, opm, Some $2, opm, rhs parseState 2, wholem) } + + | STAR + { let m = rhs parseState 1 + SynExpr.IndexRange(None, m, None, m, m, m) } + + | INFIX_AT_HAT_OP declExpr + { if not (parseState.LexBuffer.SupportsFeature LanguageFeature.FromEndSlicing) then + raiseParseErrorAt (rhs parseState 1) (FSComp.SR.fromEndSlicingRequiresVFive()) + if $1 <> "^" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidPrefixOperator()) + let m = (rhs2 parseState 1 2) + SynExpr.IndexFromEnd($2, m) } + | minusExpr %prec expr_prefix_plus_minus { $1 } dynamicArg: @@ -3900,7 +3919,7 @@ dynamicArg: let arg2 = SynExpr.Const (con, con.Range (rhs parseState 1)) arg2 } - | LPAREN typedSeqExpr rparen + | LPAREN typedSequentialExpr rparen { $2 } withClauses: @@ -3981,7 +4000,7 @@ patternGuard: { None } patternResult: - | RARROW typedSeqExprBlockR + | RARROW typedSequentialExprBlockR { $2 } ifExprCases: @@ -3999,10 +4018,10 @@ ifExprThen: | THEN declExpr %prec prec_then_if { $2, rhs parseState 1 } - | OTHEN OBLOCKBEGIN typedSeqExpr oblockend %prec prec_then_if + | OTHEN OBLOCKBEGIN typedSequentialExpr oblockend %prec prec_then_if { $3, rhs parseState 1 } - | OTHEN OBLOCKBEGIN typedSeqExpr recover %prec prec_then_if + | OTHEN OBLOCKBEGIN typedSequentialExpr recover %prec prec_then_if { if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileThen()) exprFromParseError $3, rhs parseState 1 } @@ -4014,11 +4033,11 @@ ifExprElifs: { let mElse = rhs parseState 1 Some mElse, Some $2 } - | OELSE OBLOCKBEGIN typedSeqExpr oblockend + | OELSE OBLOCKBEGIN typedSequentialExpr oblockend { let mElse = rhs parseState 1 Some mElse, Some $3 } - | OELSE OBLOCKBEGIN typedSeqExpr recover + | OELSE OBLOCKBEGIN typedSequentialExpr recover { let mElse = rhs parseState 1 if not $4 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileElse()) Some mElse, Some (exprFromParseError $3) } @@ -4097,7 +4116,22 @@ minusExpr: appExpr: | appExpr argExpr %prec expr_app - { SynExpr.App (ExprAtomicFlag.NonAtomic, false, $1, $2, unionRanges $1.Range $2.Range) } + { + // This takes '(f x)[3]' and similar forms and makes them Atomic, + // but only if they are actual applications. It doesn't effect + // the parsing precedence of this: + // g (f x)[3] + // which is still parsed as a curried application for legacy reasons + // 1111111222 + // g (f x)[3] + // 1111111222 + // This lack of spacing in curried application is given a separate warning in CheckExpressions.fs + match $2 with + | SynExpr.ArrayOrListComputed (false, _, _) + | SynExpr.ArrayOrList (false, _, _) when $1.Range.IsAdjacentTo $2.Range -> + SynExpr.App (ExprAtomicFlag.Atomic, false, $1, $2, unionRanges $1.Range $2.Range) + | _ -> + SynExpr.App (ExprAtomicFlag.NonAtomic, false, $1, $2, unionRanges $1.Range $2.Range) } | atomicExpr { let arg, _ = $1 @@ -4118,8 +4152,8 @@ argExpr: atomicExpr: | atomicExpr HIGH_PRECEDENCE_BRACK_APP atomicExpr { let arg1, _ = $1 - let arg2, _ = $3 - SynExpr.App (ExprAtomicFlag.Atomic, false, arg1, arg2, unionRanges arg1.Range arg2.Range), true } + let arg2, hpa = $3 + SynExpr.App (ExprAtomicFlag.Atomic, false, arg1, arg2, unionRanges arg1.Range arg2.Range), hpa } | atomicExpr HIGH_PRECEDENCE_PAREN_APP atomicExpr { let arg1, _ = $1 @@ -4159,11 +4193,11 @@ atomicExpr: { $1, false } | LBRACK listExprElements RBRACK - { $2 (lhs parseState) false, false } + { $2 (lhs parseState), false } | LBRACK listExprElements recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket()) - exprFromParseError ($2 (rhs2 parseState 1 2) false), false } + exprFromParseError ($2 (rhs2 parseState 1 2)), false } | LBRACK error RBRACK { // silent recovery @@ -4215,89 +4249,32 @@ atomicExprQualification: if parseState.LexBuffer.ReportLibraryOnlyFeatures then libraryOnlyError(lhs parseState) SynExpr.LibraryOnlyUnionCaseFieldGet (e, mkSynCaseName lhsm opNameCons, (fst $5), lhsm)) } - | LPAREN typedSeqExpr rparen + | LPAREN typedSequentialExpr rparen { (fun e lhsm dotm -> - mlCompatWarning (FSComp.SR.parsParenFormIsForML()) (lhs parseState) - mkSynDotParenGet lhsm dotm e $2) } - - | LBRACK typedSeqExpr RBRACK - { (fun e lhsm dotm -> mkSynDotBrackGet lhsm dotm e $2 false) } - - | LBRACK typedSeqExpr recover + // Check for expr.( * ) + // Note that "*" is parsed as an expression (it is allowed in "foo.[3,*]") + match $2 with + | SynExpr.IndexRange (None, opm, None, _m1, _m2, _) -> + mkSynDot dotm lhsm e (ident(CompileOpName "*", opm)) + | _ -> + mlCompatWarning (FSComp.SR.parsParenFormIsForML()) (lhs parseState) + mkSynDotParenGet lhsm dotm e $2) } + + | LBRACK typedSequentialExpr RBRACK + { (fun e lhsm dotm -> mkSynDotBrackGet lhsm dotm e $2) } + + | LBRACK typedSequentialExpr recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket()) - (fun e lhsm dotm -> exprFromParseError (mkSynDotBrackGet lhsm dotm e $2 false)) } - - | LBRACK optRangeSeqExpr RBRACK - { (fun e lhsm dotm -> mkSynDotBrackSeqSliceGet lhsm dotm e $2) } - - | LBRACK optRangeSeqExpr recover - { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket()) - (fun e lhsm dotm -> exprFromParseError (mkSynDotBrackSeqSliceGet lhsm dotm e $2)) } + (fun e lhsm dotm -> exprFromParseError (mkSynDotBrackGet lhsm dotm e $2)) } | LBRACK error RBRACK { let mArg = rhs2 parseState 1 3 - (fun e lhsm dotm -> mkSynDotBrackGet lhsm dotm e (arbExpr("indexerExpr1", mArg)) false) } + (fun e lhsm dotm -> mkSynDotBrackGet lhsm dotm e (arbExpr("indexerExpr1", mArg))) } | LBRACK recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracket()) let mArg = (rhs parseState 1).EndRange - (fun e lhsm dotm -> exprFromParseError (mkSynDotBrackGet lhsm dotm e (arbExpr("indexerExpr2", mArg)) false)) } - -optRangeSeqExpr: - - | optRange COMMA optRangeSeqExpr %prec slice_comma { $1 :: $3 } - - | optRange { [$1] } - -optRange: - | rangeDeclExpr DOT_DOT rangeDeclExpr - { SynIndexerArg.Two( - mkSynOptionalExpr (rhs parseState 1) (Some (fst $1)), - (snd $1), - mkSynOptionalExpr (rhs parseState 3) (Some (fst $3)), - (snd $3), - (rhs parseState 1), - (rhs parseState 3)) } - - | rangeDeclExpr DOT_DOT - { SynIndexerArg.Two( - mkSynOptionalExpr (rhs parseState 1) (Some (fst $1)), - (snd $1), - mkSynOptionalExpr (rhs parseState 2) None, - false, - (rhs parseState 1), - (rhs parseState 2)) } - - | DOT_DOT rangeDeclExpr - { SynIndexerArg.Two( - mkSynOptionalExpr (rhs parseState 1) None, - false, - mkSynOptionalExpr (rhs parseState 2) (Some (fst $2)), - (snd $2), - (rhs parseState 2), - (rhs parseState 1)) } - - | STAR - { SynIndexerArg.Two( - mkSynOptionalExpr (rhs parseState 1) None, - false, - (mkSynOptionalExpr (rhs parseState 1) None), - false, - (rhs parseState 1), - (rhs parseState 1)) } - - | rangeDeclExpr - { SynIndexerArg.One((fst $1), (snd $1), (rhs parseState 1)) } - -rangeDeclExpr: - | declExpr %prec slice_expr - { $1, false } - - | INFIX_AT_HAT_OP declExpr %prec slice_expr - { if not (parseState.LexBuffer.SupportsFeature LanguageFeature.FromEndSlicing) then - raiseParseErrorAt (rhs parseState 1) (FSComp.SR.fromEndSlicingRequiresVFive()) - if $1 <> "^" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidPrefixOperator()) - $2, true } + (fun e lhsm dotm -> exprFromParseError (mkSynDotBrackGet lhsm dotm e (arbExpr("indexerExpr2", mArg)))) } /* the start of atomicExprAfterType must not overlap with the valid postfix tokens of the type syntax, e.g. new List(...) */ atomicExprAfterType: @@ -4336,10 +4313,10 @@ atomicExprAfterType: { $1 } beginEndExpr: - | BEGIN typedSeqExpr END + | BEGIN typedSequentialExpr END { SynExpr.Paren ($2, rhs parseState 1, Some(rhs parseState 3), rhs2 parseState 1 3) } - | BEGIN typedSeqExpr recover + | BEGIN typedSequentialExpr recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBegin()); exprFromParseError $2 } | BEGIN error END @@ -4349,11 +4326,11 @@ beginEndExpr: { mkSynUnit (lhs parseState) } quoteExpr: - | LQUOTE typedSeqExpr RQUOTE + | LQUOTE typedSequentialExpr RQUOTE { if $1 <> $3 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsMismatchedQuote(fst $1)) (SynExpr.Quote (mkSynIdGet (lhs parseState) (CompileOpName (fst $1)), snd $1, $2, false, lhs parseState)) } - | LQUOTE typedSeqExpr recover + | LQUOTE typedSequentialExpr recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatched(fst $1)) let mExpr = rhs2 parseState 1 2 exprFromParseError (SynExpr.Quote (mkSynIdGet (lhs parseState) (CompileOpName (fst $1)), snd $1, $2, false, mExpr)) } @@ -4366,12 +4343,12 @@ quoteExpr: exprFromParseError (SynExpr.Quote (mkSynIdGet (lhs parseState) (CompileOpName (fst $1)), snd $1, arbExpr("quoteExpr2", (rhs parseState 1).EndRange), false, rhs parseState 1)) } arrayExpr: - | LBRACK_BAR listExprElements BAR_RBRACK - { $2 (lhs parseState) true } + | LBRACK_BAR arrayExprElements BAR_RBRACK + { $2 (lhs parseState) } - | LBRACK_BAR listExprElements recover + | LBRACK_BAR arrayExprElements recover { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedBracketBar()) - exprFromParseError ($2 (rhs2 parseState 1 2) true) } + exprFromParseError ($2 (rhs2 parseState 1 2)) } | LBRACK_BAR error BAR_RBRACK { (* silent recovery *) SynExpr.ArrayOrList (true, [ ], lhs parseState) } @@ -4430,10 +4407,10 @@ parenExpr: //arbExpr("parenExpr2", lhsm) } parenExprBody: - | staticallyKnownHeadTypars COLON LPAREN classMemberSpfn rparen typedSeqExpr + | staticallyKnownHeadTypars COLON LPAREN classMemberSpfn rparen typedSequentialExpr { (fun m -> SynExpr.TraitCall ($1, $4, $6, m)) } /* disambiguate: x $a.id(x) */ - | typedSeqExpr + | typedSequentialExpr { (fun _m -> $1) } | inlineAssemblyExpr @@ -4483,60 +4460,35 @@ braceExprBody: | objExpr { $1 } - | monadicExprInitial - { let m, r = $1 in (m, r false) } + | computationExpr + { $1 } listExprElements: - | monadicExprInitial - { let m, r = $1 in (fun lhsm isArray -> SynExpr.ArrayOrListOfSeqExpr (isArray, r true m, lhsm)) } + | sequentialExpr + { (fun lhsm -> SynExpr.ArrayOrListComputed (false, $1, lhsm)) } | - { (fun lhsm isArray -> SynExpr.ArrayOrList (isArray, [ ], lhsm)) } + { (fun lhsm -> SynExpr.ArrayOrList (false, [ ], lhsm)) } -monadicExprInitial: - | seqExpr - { $1.Range, (fun isArrayOrList lhsm -> SynExpr.CompExpr (isArrayOrList, ref(isArrayOrList), $1, lhsm)) } +arrayExprElements: + | sequentialExpr + { (fun lhsm -> SynExpr.ArrayOrListComputed (true, $1, lhsm)) } - | rangeSequenceExpr - { $1 } - -rangeSequenceExpr: - | declExpr DOT_DOT declExpr - { let opm = (rhs parseState 2) - (unionRanges $1.Range $3.Range), (fun _isArray wholem -> - // in the case of "{ 1 .. 10 }", we want the range of the expression to include the curlies, that comes from a higher level rule in the grammar, - // passed down as 'wholem', so patch up that range here - match (mkSynInfix opm $1 ".." $3) with - | SynExpr.App (a, b, c, d, _) -> SynExpr.App (a, b, c, d, wholem) - | _ -> failwith "impossible") } - - | declExpr DOT_DOT declExpr DOT_DOT declExpr - { (unionRanges $1.Range $5.Range), (fun _isArray wholem -> mkSynTrifix wholem ".. .." $1 $3 $5) } - - | declExpr DOT_DOT recover - { if not $3 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEndOfFileExpression()) - let opm = (rhs parseState 2) - let e = arbExpr("rangeSeqError1", (rhs parseState 3).StartRange) - (unionRanges $1.Range e.Range), (fun _isArray wholem -> - // in the case of "{ 1 .. 10 }", we want the range of the expression to include the curlies, that comes from a higher level rule in the grammar, - // passed down as 'wholem', so patch up that range here - match (mkSynInfix opm $1 ".." e) with - | SynExpr.App (a, b, c, d, _) -> SynExpr.App (a, b, c, d, wholem) - | _ -> failwith "impossible") } + | + { (fun lhsm -> SynExpr.ArrayOrList (true, [ ], lhsm)) } +computationExpr: + | sequentialExpr + { $1.Range, (fun lhsm -> SynExpr.ComputationExpr (false, $1, lhsm)) } arrowThenExprR: - | RARROW typedSeqExprBlockR + | RARROW typedSequentialExprBlockR { SynExpr.YieldOrReturn ((true, false), $2, unionRanges (rhs parseState 1) $2.Range) } - forLoopBinder: | parenPattern IN declExpr { ($1, $3, true) } - | parenPattern IN rangeSequenceExpr - { let m, r = $3 in ($1, r false m, true) } - | parenPattern IN ends_coming_soon_or_recover { if not $3 then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsExpectedExpressionAfterToken()) ($1, arbExpr("forLoopBinder", (rhs parseState 2)), false) } @@ -4549,9 +4501,6 @@ forLoopRange: | parenPattern EQUALS declExpr forLoopDirection declExpr { idOfPat parseState (rhs parseState 1) $1, $3, $4, $5 } - | parenPattern EQUALS rangeSequenceExpr - { raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedSymbolEqualsInsteadOfIn()) } - forLoopDirection: | TO { true } @@ -4837,7 +4786,7 @@ braceBarExprCore: (fun isStruct -> SynExpr.AnonRecd (isStruct, None, [], m)) } anonLambdaExpr: - | FUN atomicPatterns RARROW typedSeqExprBlock + | FUN atomicPatterns RARROW typedSequentialExprBlock { let mAll = unionRanges (rhs parseState 1) $4.Range mkSynFunMatchLambdas parseState.SynArgNameGenerator false mAll $2 $4 } @@ -4845,11 +4794,11 @@ anonLambdaExpr: { let mAll = rhs2 parseState 1 3 mkSynFunMatchLambdas parseState.SynArgNameGenerator false mAll $2 (arbExpr("anonLambdaExpr1", (rhs parseState 4))) } - | OFUN atomicPatterns RARROW typedSeqExprBlockR OEND + | OFUN atomicPatterns RARROW typedSequentialExprBlockR OEND { let mAll = unionRanges (rhs parseState 1) $4.Range mkSynFunMatchLambdas parseState.SynArgNameGenerator false mAll $2 $4 } - | OFUN atomicPatterns RARROW typedSeqExprBlockR recover + | OFUN atomicPatterns RARROW typedSequentialExprBlockR recover { if not $5 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedEndOfFileFunBody()); let mAll = unionRanges (rhs parseState 1) $4.Range exprFromParseError (mkSynFunMatchLambdas parseState.SynArgNameGenerator false mAll $2 $4) } diff --git a/src/fsharp/range.fs b/src/fsharp/range.fs index 68bf286fe4d..b9d43ee376b 100755 --- a/src/fsharp/range.fs +++ b/src/fsharp/range.fs @@ -56,6 +56,9 @@ type Position(code:int64) = override p.ToString() = sprintf "(%d,%d)" p.Line p.Column + member p.IsAdjacentTo(otherPos: Position) = + p.Line = otherPos.Line && p.Column + 1 = otherPos.Column + and pos = Position [] @@ -274,6 +277,9 @@ type Range(code1:int64, code2: int64) = member r.MakeSynthetic() = range(code1, code2 ||| isSyntheticMask) + member r.IsAdjacentTo(otherRange: Range) = + r.FileIndex = otherRange.FileIndex && r.End.Encoding = otherRange.Start.Encoding + member r.NoteDebugPoint(kind) = let code = match kind with @@ -391,7 +397,8 @@ module Range = let e = if (m1.EndLine > m2.EndLine || (m1.EndLine = m2.EndLine && m1.EndColumn > m2.EndColumn)) then m1 else m2 - range (m1.FileIndex, b.StartLine, b.StartColumn, e.EndLine, e.EndColumn) + let m = range (m1.FileIndex, b.StartLine, b.StartColumn, e.EndLine, e.EndColumn) + if m1.IsSynthetic || m2.IsSynthetic then m.MakeSynthetic() else m let rangeContainsRange (m1:range) (m2:range) = m1.FileIndex = m2.FileIndex && diff --git a/src/fsharp/range.fsi b/src/fsharp/range.fsi index 13d604afee4..8913f498b07 100755 --- a/src/fsharp/range.fsi +++ b/src/fsharp/range.fsi @@ -30,6 +30,9 @@ type Position = /// The encoding of the position as a 64-bit integer member internal Encoding: int64 + /// Check if the position is adjacent to another postition + member internal IsAdjacentTo: otherPos: Position -> bool + /// Decode a position fro a 64-bit integer static member internal Decode: int64 -> pos @@ -88,6 +91,9 @@ type Range = /// Note that a range indicates a debug point member internal NoteDebugPoint: kind: RangeDebugPointKind -> range + /// Check if the range is adjacent to another range + member internal IsAdjacentTo: otherRange: Range -> bool + /// Convert a range to string member internal ToShortString: unit -> string diff --git a/src/fsharp/service/FSharpParseFileResults.fs b/src/fsharp/service/FSharpParseFileResults.fs index cae926e2481..22ef412220a 100644 --- a/src/fsharp/service/FSharpParseFileResults.fs +++ b/src/fsharp/service/FSharpParseFileResults.fs @@ -160,7 +160,7 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, match expr with | SynExpr.TypeApp (_, _, _, _, _, _, range) when rangeContainsPos range pos -> Some range - | SynExpr.App(_, _, _, SynExpr.CompExpr (_, _, expr, _), range) when rangeContainsPos range pos -> + | SynExpr.App(_, _, _, SynExpr.ComputationExpr (_, expr, _), range) when rangeContainsPos range pos -> traverseSynExpr expr | SynExpr.App (_, _, _, _, range) when rangeContainsPos range pos -> Some range @@ -186,8 +186,8 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, | SynExpr.App (_, _, _, _, range) when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr argExpr pos - // Special case: `async { ... }` is actually a CompExpr inside of the argExpr of a SynExpr.App - | SynExpr.CompExpr (_, _, expr, range) when rangeContainsPos range pos -> + // Special case: `async { ... }` is actually a ComputationExpr inside of the argExpr of a SynExpr.App + | SynExpr.ComputationExpr (_, expr, range) when rangeContainsPos range pos -> getIdentRangeForFuncExprInApp traverseSynExpr expr pos | SynExpr.Paren (expr, _, _, range) when rangeContainsPos range pos -> @@ -496,8 +496,8 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, | SynExpr.TypeTest (e, _, _) | SynExpr.Upcast (e, _, _) | SynExpr.AddressOf (_, e, _, _) - | SynExpr.CompExpr (_, _, e, _) - | SynExpr.ArrayOrListOfSeqExpr (_, e, _) + | SynExpr.ComputationExpr (_, e, _) + | SynExpr.ArrayOrListComputed (_, e, _) | SynExpr.Typed (e, _, _) | SynExpr.FromParseError (e, _) | SynExpr.DiscardAfterMissingQualificationAfterDot (e, _) @@ -627,11 +627,18 @@ type FSharpParseFileResults(diagnostics: FSharpDiagnostic[], input: ParsedInput, | SynExpr.DotIndexedGet (e1, es, _, _) -> yield! walkExpr false e1 - yield! walkExprs [ for e in es do yield! e.Exprs ] + yield! walkExpr false es + + | SynExpr.IndexRange (expr1, _, expr2, _, _, _) -> + match expr1 with Some e -> yield! walkExpr false e | None -> () + match expr2 with Some e -> yield! walkExpr false e | None -> () + + | SynExpr.IndexFromEnd (e, _) -> + yield! walkExpr false e | SynExpr.DotIndexedSet (e1, es, e2, _, _, _) -> yield! walkExpr false e1 - yield! walkExprs [ for e in es do yield! e.Exprs ] + yield! walkExpr false es yield! walkExpr false e2 | SynExpr.DotNamedIndexedPropertySet (e1, _, e2, e3, _) -> diff --git a/src/fsharp/service/ServiceInterfaceStubGenerator.fs b/src/fsharp/service/ServiceInterfaceStubGenerator.fs index 02dc5f46c1b..cf33ef41bc7 100644 --- a/src/fsharp/service/ServiceInterfaceStubGenerator.fs +++ b/src/fsharp/service/ServiceInterfaceStubGenerator.fs @@ -52,13 +52,6 @@ module internal CodeGenerationUtils = stringWriter.Dispose() indentWriter.Dispose() - let (|IndexerArg|) = function - | SynIndexerArg.Two(e1, _, e2, _, _, _) -> [e1; e2] - | SynIndexerArg.One (e, _, _) -> [e] - - let (|IndexerArgList|) xs = - List.collect (|IndexerArg|) xs - /// An recursive pattern that collect all sequential expressions to avoid StackOverflowException let rec (|Sequentials|_|) = function | SynExpr.Sequential (_, _, e, Sequentials es, _) -> @@ -808,9 +801,9 @@ module InterfaceStubGenerator = | SynExpr.For (_sequencePointInfoForForLoop, _ident, synExpr1, _, synExpr2, synExpr3, _range) -> List.tryPick walkExpr [synExpr1; synExpr2; synExpr3] - | SynExpr.ArrayOrListOfSeqExpr (_, synExpr, _range) -> + | SynExpr.ArrayOrListComputed (_, synExpr, _range) -> walkExpr synExpr - | SynExpr.CompExpr (_, _, synExpr, _range) -> + | SynExpr.ComputationExpr (_, synExpr, _range) -> walkExpr synExpr | SynExpr.Lambda (_, _, _synSimplePats, synExpr, _, _range) -> walkExpr synExpr @@ -871,13 +864,11 @@ module InterfaceStubGenerator = | SynExpr.Set (synExpr1, synExpr2, _range) -> List.tryPick walkExpr [synExpr1; synExpr2] - | SynExpr.DotIndexedGet (synExpr, IndexerArgList synExprList, _range, _range2) -> - Option.orElse (walkExpr synExpr) (List.tryPick walkExpr synExprList) + | SynExpr.DotIndexedGet (synExpr, indexArgs, _range, _range2) -> + Option.orElse (walkExpr synExpr) (walkExpr indexArgs) - | SynExpr.DotIndexedSet (synExpr1, IndexerArgList synExprList, synExpr2, _, _range, _range2) -> - [ yield synExpr1 - yield! synExprList - yield synExpr2 ] + | SynExpr.DotIndexedSet (synExpr1, indexArgs, synExpr2, _, _range, _range2) -> + [ synExpr1; indexArgs; synExpr2 ] |> List.tryPick walkExpr | SynExpr.JoinIn (synExpr1, _range, synExpr2, _range2) -> diff --git a/src/fsharp/service/ServiceParseTreeWalk.fs b/src/fsharp/service/ServiceParseTreeWalk.fs index 8a5244cdfd5..9d5e04c6178 100755 --- a/src/fsharp/service/ServiceParseTreeWalk.fs +++ b/src/fsharp/service/ServiceParseTreeWalk.fs @@ -405,16 +405,16 @@ module SyntaxTraversal = dive synExpr2 synExpr2.Range traverseSynExpr] |> pick expr - | SynExpr.ArrayOrListOfSeqExpr (_, synExpr, _range) -> traverseSynExpr synExpr + | SynExpr.ArrayOrListComputed (_, synExpr, _range) -> traverseSynExpr synExpr - | SynExpr.CompExpr (_, _, synExpr, _range) -> + | SynExpr.ComputationExpr (_, synExpr, _range) -> // now parser treats this syntactic expression as computation expression // { identifier } - // here we detect this situation and treat CompExpr { Identifier } as attempt to create record - // note: sequence expressions use SynExpr.CompExpr too - they need to be filtered out + // here we detect this situation and treat ComputationExpr { Identifier } as attempt to create record + // note: sequence expressions use SynExpr.ComputationExpr too - they need to be filtered out let isPartOfArrayOrList = match origPath with - | SyntaxNode.SynExpr(SynExpr.ArrayOrListOfSeqExpr _) :: _ -> true + | SyntaxNode.SynExpr(SynExpr.ArrayOrListComputed _) :: _ -> true | _ -> false let ok = match isPartOfArrayOrList, synExpr with @@ -511,18 +511,22 @@ module SyntaxTraversal = dive synExpr2 synExpr2.Range traverseSynExpr] |> pick expr - | SynExpr.DotIndexedGet (synExpr, synExprList, _range, _range2) -> + | SynExpr.IndexRange (expr1, _, expr2, _, _, _) -> + [ match expr1 with Some e -> dive e e.Range traverseSynExpr | None -> () + match expr2 with Some e -> dive e e.Range traverseSynExpr | None -> () ] + |> pick expr + + | SynExpr.IndexFromEnd (e, _) -> + traverseSynExpr e + + | SynExpr.DotIndexedGet (synExpr, indexArgs, _range, _range2) -> [yield dive synExpr synExpr.Range traverseSynExpr - for synExpr in synExprList do - for x in synExpr.Exprs do - yield dive x x.Range traverseSynExpr] + yield dive indexArgs indexArgs.Range traverseSynExpr] |> pick expr - | SynExpr.DotIndexedSet (synExpr, synExprList, synExpr2, _, _range, _range2) -> + | SynExpr.DotIndexedSet (synExpr, indexArgs, synExpr2, _, _range, _range2) -> [yield dive synExpr synExpr.Range traverseSynExpr - for synExpr in synExprList do - for x in synExpr.Exprs do - yield dive x x.Range traverseSynExpr + yield dive indexArgs indexArgs.Range traverseSynExpr yield dive synExpr2 synExpr2.Range traverseSynExpr] |> pick expr diff --git a/src/fsharp/service/ServiceParsedInputOps.fs b/src/fsharp/service/ServiceParsedInputOps.fs index 8e6bf226c45..5e00f7b0764 100644 --- a/src/fsharp/service/ServiceParsedInputOps.fs +++ b/src/fsharp/service/ServiceParsedInputOps.fs @@ -455,46 +455,46 @@ module ParsedInput = and walkSynModuleOrNamespace isTopLevel (SynModuleOrNamespace(_, _, _, decls, _, Attributes attrs, _, r)) = List.tryPick walkAttribute attrs - |> Option.orElse (ifPosInRange r (fun _ -> List.tryPick (walkSynModuleDecl isTopLevel) decls)) + |> Option.orElseWith (fun () -> ifPosInRange r (fun _ -> List.tryPick (walkSynModuleDecl isTopLevel) decls)) and walkAttribute (attr: SynAttribute) = if isPosInRange attr.Range then Some EntityKind.Attribute else None - |> Option.orElse (walkExprWithKind (Some EntityKind.Type) attr.ArgExpr) + |> Option.orElseWith (fun () -> walkExprWithKind (Some EntityKind.Type) attr.ArgExpr) and walkTypar (SynTypar (ident, _, _)) = ifPosInRange ident.idRange (fun _ -> Some EntityKind.Type) and walkTyparDecl (SynTyparDecl.SynTyparDecl (Attributes attrs, typar)) = List.tryPick walkAttribute attrs - |> Option.orElse (walkTypar typar) + |> Option.orElseWith (fun () -> walkTypar typar) and walkTypeConstraint = function - | SynTypeConstraint.WhereTyparDefaultsToType (t1, t2, _) -> walkTypar t1 |> Option.orElse (walkType t2) + | SynTypeConstraint.WhereTyparDefaultsToType (t1, t2, _) -> walkTypar t1 |> Option.orElseWith (fun () -> walkType t2) | SynTypeConstraint.WhereTyparIsValueType(t, _) -> walkTypar t | SynTypeConstraint.WhereTyparIsReferenceType(t, _) -> walkTypar t | SynTypeConstraint.WhereTyparIsUnmanaged(t, _) -> walkTypar t | SynTypeConstraint.WhereTyparSupportsNull (t, _) -> walkTypar t | SynTypeConstraint.WhereTyparIsComparable(t, _) -> walkTypar t | SynTypeConstraint.WhereTyparIsEquatable(t, _) -> walkTypar t - | SynTypeConstraint.WhereTyparSubtypeOfType(t, ty, _) -> walkTypar t |> Option.orElse (walkType ty) + | SynTypeConstraint.WhereTyparSubtypeOfType(t, ty, _) -> walkTypar t |> Option.orElseWith (fun () -> walkType ty) | SynTypeConstraint.WhereTyparSupportsMember(ts, sign, _) -> - List.tryPick walkType ts |> Option.orElse (walkMemberSig sign) - | SynTypeConstraint.WhereTyparIsEnum(t, ts, _) -> walkTypar t |> Option.orElse (List.tryPick walkType ts) - | SynTypeConstraint.WhereTyparIsDelegate(t, ts, _) -> walkTypar t |> Option.orElse (List.tryPick walkType ts) + List.tryPick walkType ts |> Option.orElseWith (fun () -> walkMemberSig sign) + | SynTypeConstraint.WhereTyparIsEnum(t, ts, _) -> walkTypar t |> Option.orElseWith (fun () -> List.tryPick walkType ts) + | SynTypeConstraint.WhereTyparIsDelegate(t, ts, _) -> walkTypar t |> Option.orElseWith (fun () -> List.tryPick walkType ts) and walkPatWithKind (kind: EntityKind option) = function | SynPat.Ands (pats, _) -> List.tryPick walkPat pats | SynPat.As (pat1, pat2, _) -> List.tryPick walkPat [pat1; pat2] - | SynPat.Typed(pat, t, _) -> walkPat pat |> Option.orElse (walkType t) - | SynPat.Attrib(pat, Attributes attrs, _) -> walkPat pat |> Option.orElse (List.tryPick walkAttribute attrs) + | SynPat.Typed(pat, t, _) -> walkPat pat |> Option.orElseWith (fun () -> walkType t) + | SynPat.Attrib(pat, Attributes attrs, _) -> walkPat pat |> Option.orElseWith (fun () -> List.tryPick walkAttribute attrs) | SynPat.Or(pat1, pat2, _) -> List.tryPick walkPat [pat1; pat2] | SynPat.LongIdent(_, _, typars, ConstructorPats pats, _, r) -> ifPosInRange r (fun _ -> kind) - |> Option.orElse ( + |> Option.orElseWith (fun () -> typars |> Option.bind (fun (ValTyparDecls (typars, constraints, _)) -> List.tryPick walkTyparDecl typars - |> Option.orElse (List.tryPick walkTypeConstraint constraints))) - |> Option.orElse (List.tryPick walkPat pats) + |> Option.orElseWith (fun () -> List.tryPick walkTypeConstraint constraints))) + |> Option.orElseWith (fun () -> List.tryPick walkPat pats) | SynPat.Tuple(_, pats, _) -> List.tryPick walkPat pats | SynPat.Paren(pat, _) -> walkPat pat | SynPat.ArrayOrList(_, pats, _) -> List.tryPick walkPat pats @@ -506,9 +506,9 @@ module ParsedInput = and walkBinding (SynBinding(_, _, _, _, Attributes attrs, _, _, pat, returnInfo, e, _, _)) = List.tryPick walkAttribute attrs - |> Option.orElse (walkPat pat) - |> Option.orElse (walkExpr e) - |> Option.orElse ( + |> Option.orElseWith (fun () -> walkPat pat) + |> Option.orElseWith (fun () -> walkExpr e) + |> Option.orElseWith (fun () -> match returnInfo with | Some (SynBindingReturnInfo (t, _, _)) -> walkType t | None -> None) @@ -516,42 +516,38 @@ module ParsedInput = and walkInterfaceImpl (SynInterfaceImpl(_, bindings, _)) = List.tryPick walkBinding bindings - and walkIndexerArg = function - | SynIndexerArg.One (e, _, _) -> walkExpr e - | SynIndexerArg.Two(e1, _, e2, _, _, _) -> List.tryPick walkExpr [e1; e2] - and walkType = function | SynType.LongIdent ident -> // we protect it with try..with because System.Exception : rangeOfLidwd may raise // at FSharp.Compiler.Syntax.LongIdentWithDots.get_Range() in D:\j\workspace\release_ci_pa---3f142ccc\src\fsharp\ast.fs: line 156 try ifPosInRange ident.Range (fun _ -> Some EntityKind.Type) with _ -> None | SynType.App(ty, _, types, _, _, _, _) -> - walkType ty |> Option.orElse (List.tryPick walkType types) + walkType ty |> Option.orElseWith (fun () -> List.tryPick walkType types) | SynType.LongIdentApp(_, _, _, types, _, _, _) -> List.tryPick walkType types | SynType.Tuple(_, ts, _) -> ts |> List.tryPick (fun (_, t) -> walkType t) | SynType.Array(_, t, _) -> walkType t - | SynType.Fun(t1, t2, _) -> walkType t1 |> Option.orElse (walkType t2) + | SynType.Fun(t1, t2, _) -> walkType t1 |> Option.orElseWith (fun () -> walkType t2) | SynType.WithGlobalConstraints(t, _, _) -> walkType t | SynType.HashConstraint(t, _) -> walkType t - | SynType.MeasureDivide(t1, t2, _) -> walkType t1 |> Option.orElse (walkType t2) + | SynType.MeasureDivide(t1, t2, _) -> walkType t1 |> Option.orElseWith (fun () -> walkType t2) | SynType.MeasurePower(t, _, _) -> walkType t | SynType.Paren(t, _) -> walkType t | _ -> None and walkClause (SynMatchClause(pat, e1, e2, _, _)) = walkPatWithKind (Some EntityKind.Type) pat - |> Option.orElse (walkExpr e2) - |> Option.orElse (Option.bind walkExpr e1) + |> Option.orElseWith (fun () -> walkExpr e2) + |> Option.orElseWith (fun () -> Option.bind walkExpr e1) and walkExprWithKind (parentKind: EntityKind option) = function | SynExpr.LongIdent (_, LongIdentWithDots(_, dotRanges), _, r) -> match dotRanges with - | [] when isPosInRange r -> parentKind |> Option.orElse (Some (EntityKind.FunctionOrValue false)) + | [] when isPosInRange r -> parentKind |> Option.orElseWith (fun () -> Some (EntityKind.FunctionOrValue false)) | firstDotRange :: _ -> let firstPartRange = mkRange "" r.Start (mkPos firstDotRange.StartLine (firstDotRange.StartColumn - 1)) if isPosInRange firstPartRange then - parentKind |> Option.orElse (Some (EntityKind.FunctionOrValue false)) + parentKind |> Option.orElseWith (fun () -> Some (EntityKind.FunctionOrValue false)) else None | _ -> None | SynExpr.Paren (e, _, _, _) -> walkExprWithKind parentKind e @@ -562,45 +558,45 @@ module ParsedInput = | SynExpr.Record (_, _, fields, r) -> ifPosInRange r (fun _ -> fields |> List.tryPick (fun (_, e, _) -> e |> Option.bind (walkExprWithKind parentKind))) - | SynExpr.New (_, t, e, _) -> walkExprWithKind parentKind e |> Option.orElse (walkType t) + | SynExpr.New (_, t, e, _) -> walkExprWithKind parentKind e |> Option.orElseWith (fun () -> walkType t) | SynExpr.ObjExpr (ty, _, bindings, ifaces, _, _) -> walkType ty - |> Option.orElse (List.tryPick walkBinding bindings) - |> Option.orElse (List.tryPick walkInterfaceImpl ifaces) + |> Option.orElseWith (fun () -> List.tryPick walkBinding bindings) + |> Option.orElseWith (fun () -> List.tryPick walkInterfaceImpl ifaces) | SynExpr.While (_, e1, e2, _) -> List.tryPick (walkExprWithKind parentKind) [e1; e2] | SynExpr.For (_, _, e1, _, e2, e3, _) -> List.tryPick (walkExprWithKind parentKind) [e1; e2; e3] | SynExpr.ForEach (_, _, _, _, e1, e2, _) -> List.tryPick (walkExprWithKind parentKind) [e1; e2] - | SynExpr.ArrayOrListOfSeqExpr (_, e, _) -> walkExprWithKind parentKind e - | SynExpr.CompExpr (_, _, e, _) -> walkExprWithKind parentKind e + | SynExpr.ArrayOrListComputed (_, e, _) -> walkExprWithKind parentKind e + | SynExpr.ComputationExpr (_, e, _) -> walkExprWithKind parentKind e | SynExpr.Lambda (_, _, _, e, _, _) -> walkExprWithKind parentKind e | SynExpr.MatchLambda (_, _, synMatchClauseList, _, _) -> List.tryPick walkClause synMatchClauseList | SynExpr.Match (_, e, synMatchClauseList, _) -> - walkExprWithKind parentKind e |> Option.orElse (List.tryPick walkClause synMatchClauseList) + walkExprWithKind parentKind e |> Option.orElseWith (fun () -> List.tryPick walkClause synMatchClauseList) | SynExpr.Do (e, _) -> walkExprWithKind parentKind e | SynExpr.Assert (e, _) -> walkExprWithKind parentKind e | SynExpr.App (_, _, e1, e2, _) -> List.tryPick (walkExprWithKind parentKind) [e1; e2] | SynExpr.TypeApp (e, _, tys, _, _, _, _) -> - walkExprWithKind (Some EntityKind.Type) e |> Option.orElse (List.tryPick walkType tys) - | SynExpr.LetOrUse (_, _, bindings, e, _) -> List.tryPick walkBinding bindings |> Option.orElse (walkExprWithKind parentKind e) - | SynExpr.TryWith (e, _, clauses, _, _, _, _) -> walkExprWithKind parentKind e |> Option.orElse (List.tryPick walkClause clauses) + walkExprWithKind (Some EntityKind.Type) e |> Option.orElseWith (fun () -> List.tryPick walkType tys) + | SynExpr.LetOrUse (_, _, bindings, e, _) -> List.tryPick walkBinding bindings |> Option.orElseWith (fun () -> walkExprWithKind parentKind e) + | SynExpr.TryWith (e, _, clauses, _, _, _, _) -> walkExprWithKind parentKind e |> Option.orElseWith (fun () -> List.tryPick walkClause clauses) | SynExpr.TryFinally (e1, e2, _, _, _) -> List.tryPick (walkExprWithKind parentKind) [e1; e2] | SynExpr.Lazy (e, _) -> walkExprWithKind parentKind e | Sequentials es -> List.tryPick (walkExprWithKind parentKind) es | SynExpr.IfThenElse (_, _, e1, _, e2, _, e3, _, _, _, _) -> - List.tryPick (walkExprWithKind parentKind) [e1; e2] |> Option.orElse (match e3 with None -> None | Some e -> walkExprWithKind parentKind e) + List.tryPick (walkExprWithKind parentKind) [e1; e2] |> Option.orElseWith (fun () -> match e3 with None -> None | Some e -> walkExprWithKind parentKind e) | SynExpr.Ident ident -> ifPosInRange ident.idRange (fun _ -> Some (EntityKind.FunctionOrValue false)) | SynExpr.LongIdentSet (_, e, _) -> walkExprWithKind parentKind e | SynExpr.DotGet (e, _, _, _) -> walkExprWithKind parentKind e | SynExpr.DotSet (e, _, _, _) -> walkExprWithKind parentKind e | SynExpr.Set (e, _, _) -> walkExprWithKind parentKind e - | SynExpr.DotIndexedGet (e, args, _, _) -> walkExprWithKind parentKind e |> Option.orElse (List.tryPick walkIndexerArg args) - | SynExpr.DotIndexedSet (e, args, _, _, _, _) -> walkExprWithKind parentKind e |> Option.orElse (List.tryPick walkIndexerArg args) + | SynExpr.DotIndexedGet (e, args, _, _) -> walkExprWithKind parentKind e |> Option.orElseWith (fun () -> walkExprWithKind parentKind args) + | SynExpr.DotIndexedSet (e, args, _, _, _, _) -> walkExprWithKind parentKind e |> Option.orElseWith (fun () -> walkExprWithKind parentKind args) | SynExpr.NamedIndexedPropertySet (_, e1, e2, _) -> List.tryPick (walkExprWithKind parentKind) [e1; e2] | SynExpr.DotNamedIndexedPropertySet (e1, _, e2, e3, _) -> List.tryPick (walkExprWithKind parentKind) [e1; e2; e3] - | SynExpr.TypeTest (e, t, _) -> walkExprWithKind parentKind e |> Option.orElse (walkType t) - | SynExpr.Upcast (e, t, _) -> walkExprWithKind parentKind e |> Option.orElse (walkType t) - | SynExpr.Downcast (e, t, _) -> walkExprWithKind parentKind e |> Option.orElse (walkType t) + | SynExpr.TypeTest (e, t, _) -> walkExprWithKind parentKind e |> Option.orElseWith (fun () -> walkType t) + | SynExpr.Upcast (e, t, _) -> walkExprWithKind parentKind e |> Option.orElseWith (fun () -> walkType t) + | SynExpr.Downcast (e, t, _) -> walkExprWithKind parentKind e |> Option.orElseWith (fun () -> walkType t) | SynExpr.InferredUpcast (e, _) -> walkExprWithKind parentKind e | SynExpr.InferredDowncast (e, _) -> walkExprWithKind parentKind e | SynExpr.AddressOf (_, e, _, _) -> walkExprWithKind parentKind e @@ -609,7 +605,7 @@ module ParsedInput = | SynExpr.YieldOrReturnFrom (_, e, _) -> walkExprWithKind parentKind e | SynExpr.Match (_, e, synMatchClauseList, _) | SynExpr.MatchBang (_, e, synMatchClauseList, _) -> - walkExprWithKind parentKind e |> Option.orElse (List.tryPick walkClause synMatchClauseList) + walkExprWithKind parentKind e |> Option.orElseWith (fun () -> List.tryPick walkClause synMatchClauseList) | SynExpr.LetOrUseBang(_, _, _, _, e1, es, e2, _) -> [ yield e1 @@ -621,23 +617,23 @@ module ParsedInput = | SynExpr.DoBang (e, _) -> walkExprWithKind parentKind e | SynExpr.TraitCall (ts, sign, e, _) -> List.tryPick walkTypar ts - |> Option.orElse (walkMemberSig sign) - |> Option.orElse (walkExprWithKind parentKind e) + |> Option.orElseWith (fun () -> walkMemberSig sign) + |> Option.orElseWith (fun () -> walkExprWithKind parentKind e) | _ -> None and walkExpr = walkExprWithKind None and walkSimplePat = function | SynSimplePat.Attrib (pat, Attributes attrs, _) -> - walkSimplePat pat |> Option.orElse (List.tryPick walkAttribute attrs) - | SynSimplePat.Typed(pat, t, _) -> walkSimplePat pat |> Option.orElse (walkType t) + walkSimplePat pat |> Option.orElseWith (fun () -> List.tryPick walkAttribute attrs) + | SynSimplePat.Typed(pat, t, _) -> walkSimplePat pat |> Option.orElseWith (fun () -> walkType t) | _ -> None and walkField (SynField(Attributes attrs, _, _, t, _, _, _, _)) = - List.tryPick walkAttribute attrs |> Option.orElse (walkType t) + List.tryPick walkAttribute attrs |> Option.orElseWith (fun () -> walkType t) and walkValSig (SynValSig(Attributes attrs, _, _, t, _, _, _, _, _, _, _)) = - List.tryPick walkAttribute attrs |> Option.orElse (walkType t) + List.tryPick walkAttribute attrs |> Option.orElseWith (fun () -> walkType t) and walkMemberSig = function | SynMemberSig.Inherit (t, _) -> walkType t @@ -646,25 +642,25 @@ module ParsedInput = | SynMemberSig.ValField(f, _) -> walkField f | SynMemberSig.NestedType(SynTypeDefnSig.SynTypeDefnSig (info, repr, memberSigs, _), _) -> walkComponentInfo false info - |> Option.orElse (walkTypeDefnSigRepr repr) - |> Option.orElse (List.tryPick walkMemberSig memberSigs) + |> Option.orElseWith (fun () -> walkTypeDefnSigRepr repr) + |> Option.orElseWith (fun () -> List.tryPick walkMemberSig memberSigs) and walkMember = function | SynMemberDefn.AbstractSlot (valSig, _, _) -> walkValSig valSig | SynMemberDefn.Member(binding, _) -> walkBinding binding | SynMemberDefn.ImplicitCtor(_, Attributes attrs, SynSimplePats.SimplePats(simplePats, _), _, _, _) -> - List.tryPick walkAttribute attrs |> Option.orElse (List.tryPick walkSimplePat simplePats) - | SynMemberDefn.ImplicitInherit(t, e, _, _) -> walkType t |> Option.orElse (walkExpr e) + List.tryPick walkAttribute attrs |> Option.orElseWith (fun () -> List.tryPick walkSimplePat simplePats) + | SynMemberDefn.ImplicitInherit(t, e, _, _) -> walkType t |> Option.orElseWith (fun () -> walkExpr e) | SynMemberDefn.LetBindings(bindings, _, _, _) -> List.tryPick walkBinding bindings | SynMemberDefn.Interface(t, members, _) -> - walkType t |> Option.orElse (members |> Option.bind (List.tryPick walkMember)) + walkType t |> Option.orElseWith (fun () -> members |> Option.bind (List.tryPick walkMember)) | SynMemberDefn.Inherit(t, _, _) -> walkType t | SynMemberDefn.ValField(field, _) -> walkField field | SynMemberDefn.NestedType(tdef, _, _) -> walkTypeDefn tdef | SynMemberDefn.AutoProperty(Attributes attrs, _, _, t, _, _, _, _, e, _, _) -> List.tryPick walkAttribute attrs - |> Option.orElse (Option.bind walkType t) - |> Option.orElse (walkExpr e) + |> Option.orElseWith (fun () -> Option.bind walkType t) + |> Option.orElseWith (fun () -> walkExpr e) | _ -> None and walkEnumCase (SynEnumCase(Attributes attrs, _, _, _, _, _)) = List.tryPick walkAttribute attrs @@ -674,7 +670,7 @@ module ParsedInput = | SynUnionCaseKind.FullType(t, _) -> walkType t and walkUnionCase (SynUnionCase(Attributes attrs, _, t, _, _, _)) = - List.tryPick walkAttribute attrs |> Option.orElse (walkUnionCaseType t) + List.tryPick walkAttribute attrs |> Option.orElseWith (fun () -> walkUnionCaseType t) and walkTypeDefnSimple = function | SynTypeDefnSimpleRepr.Enum (cases, _) -> List.tryPick walkEnumCase cases @@ -686,10 +682,10 @@ module ParsedInput = and walkComponentInfo isModule (SynComponentInfo(Attributes attrs, TyparsAndConstraints (typars, cs1), cs2, _, _, _, _, r)) = let constraints = cs1 @ cs2 if isModule then None else ifPosInRange r (fun _ -> Some EntityKind.Type) - |> Option.orElse ( + |> Option.orElseWith (fun () -> List.tryPick walkAttribute attrs - |> Option.orElse (List.tryPick walkTyparDecl typars) - |> Option.orElse (List.tryPick walkTypeConstraint constraints)) + |> Option.orElseWith (fun () -> List.tryPick walkTyparDecl typars) + |> Option.orElseWith (fun () -> List.tryPick walkTypeConstraint constraints)) and walkTypeDefnRepr = function | SynTypeDefnRepr.ObjectModel (_, defns, _) -> List.tryPick walkMember defns @@ -703,15 +699,15 @@ module ParsedInput = and walkTypeDefn (SynTypeDefn (info, repr, members, _, _)) = walkComponentInfo false info - |> Option.orElse (walkTypeDefnRepr repr) - |> Option.orElse (List.tryPick walkMember members) + |> Option.orElseWith (fun () -> walkTypeDefnRepr repr) + |> Option.orElseWith (fun () -> List.tryPick walkMember members) and walkSynModuleDecl isTopLevel (decl: SynModuleDecl) = match decl with | SynModuleDecl.NamespaceFragment fragment -> walkSynModuleOrNamespace isTopLevel fragment | SynModuleDecl.NestedModule(info, _, modules, _, range) -> walkComponentInfo true info - |> Option.orElse (ifPosInRange range (fun _ -> List.tryPick (walkSynModuleDecl false) modules)) + |> Option.orElseWith (fun () -> ifPosInRange range (fun _ -> List.tryPick (walkSynModuleDecl false) modules)) | SynModuleDecl.Open _ -> None | SynModuleDecl.Let (_, bindings, _) -> List.tryPick walkBinding bindings | SynModuleDecl.DoExpr (_, expr, _) -> walkExpr expr @@ -826,9 +822,9 @@ module ParsedInput = | _ -> None // checks if we are in rhs of the range operator - let isInRhsOfRangeOp (p : SyntaxVisitorPath) = + let isAtRangeOp (p : SyntaxVisitorPath) = match p with - | SyntaxNode.SynExpr(Operator "op_Range" _) :: _ -> true + | SyntaxNode.SynExpr(SynExpr.IndexRange(Some _, _, None, _, _, _)) :: _ -> true | _ -> false let (|Setter|_|) e = @@ -917,7 +913,7 @@ module ParsedInput = new SyntaxVisitorBase<_>() with member _.VisitExpr(path, _, defaultTraverse, expr) = - if isInRhsOfRangeOp path then + if isAtRangeOp path then match defaultTraverse expr with | None -> Some CompletionContext.RangeOperator // nothing was found - report that we were in the context of range operator | x -> x // ok, we found something - return it @@ -1231,10 +1227,6 @@ module ParsedInput = and walkInterfaceImpl (SynInterfaceImpl(_, bindings, _)) = List.iter walkBinding bindings - and walkIndexerArg = function - | SynIndexerArg.One (e, _, _) -> walkExpr e - | SynIndexerArg.Two (e1, _, e2, _, _, _) -> List.iter walkExpr [e1; e2] - and walkType = function | SynType.Array (_, t, _) | SynType.HashConstraint (t, _) @@ -1270,8 +1262,8 @@ module ParsedInput = | SynExpr.AddressOf (_, e, _, _) | SynExpr.DoBang (e, _) | SynExpr.YieldOrReturn (_, e, _) - | SynExpr.ArrayOrListOfSeqExpr (_, e, _) - | SynExpr.CompExpr (_, _, e, _) + | SynExpr.ArrayOrListComputed (_, e, _) + | SynExpr.ComputationExpr (_, e, _) | SynExpr.Do (e, _) | SynExpr.Assert (e, _) | SynExpr.Lazy (e, _) @@ -1333,12 +1325,17 @@ module ParsedInput = | SynExpr.Set (e1, e2, _) -> walkExpr e1 walkExpr e2 + | SynExpr.IndexRange (expr1, _, expr2, _, _, _) -> + match expr1 with Some e -> walkExpr e | None -> () + match expr2 with Some e -> walkExpr e | None -> () + | SynExpr.IndexFromEnd (e, _) -> + walkExpr e | SynExpr.DotIndexedGet (e, args, _, _) -> walkExpr e - List.iter walkIndexerArg args + walkExpr args | SynExpr.DotIndexedSet (e1, args, e2, _, _, _) -> walkExpr e1 - List.iter walkIndexerArg args + walkExpr args walkExpr e2 | SynExpr.NamedIndexedPropertySet (ident, e1, e2, _) -> addLongIdentWithDots ident diff --git a/src/fsharp/service/ServiceStructure.fs b/src/fsharp/service/ServiceStructure.fs index 1f7cb12fef8..dd6ea1dc92b 100644 --- a/src/fsharp/service/ServiceStructure.fs +++ b/src/fsharp/service/ServiceStructure.fs @@ -90,7 +90,7 @@ module Structure = | Member | LetOrUse | Val - | CompExpr + | ComputationExpr | IfThenElse | ThenInIfThenElse | ElseInIfThenElse @@ -140,7 +140,7 @@ module Structure = | Member -> "Member" | LetOrUse -> "LetOrUse" | Val -> "Val" - | CompExpr -> "CompExpr" + | ComputationExpr -> "ComputationExpr" | IfThenElse -> "IfThenElse" | ThenInIfThenElse -> "ThenInIfThenElse" | ElseInIfThenElse -> "ElseInIfThenElse" @@ -292,24 +292,24 @@ module Structure = // seq exprs, custom operators, etc if ExprAtomicFlag.NonAtomic=atomicFlag && (not isInfix) && (function SynExpr.Ident _ -> true | _ -> false) funcExpr - && (function SynExpr.CompExpr _ -> false | _ -> true ) argExpr then + && (function SynExpr.ComputationExpr _ -> false | _ -> true ) argExpr then // if the argExpr is a computation expression another match will handle the outlining // these cases must be removed to prevent creating unnecessary tags for the same scope let collapse = Range.endToEnd funcExpr.Range r rcheck Scope.SpecialFunc Collapse.Below r collapse elif ExprAtomicFlag.NonAtomic=atomicFlag && (not isInfix) - && (function SynExpr.CompExpr _ -> true | _ -> false) argExpr then + && (function SynExpr.ComputationExpr _ -> true | _ -> false) argExpr then let collapse = Range.startToEnd argExpr.Range r - rcheck Scope.CompExpr Collapse.Same r <| Range.modBoth 1 1 collapse + rcheck Scope.ComputationExpr Collapse.Same r <| Range.modBoth 1 1 collapse parseExpr argExpr parseExpr funcExpr | SynExpr.Sequential (_, _, e1, e2, _) -> parseExpr e1 parseExpr e2 - | SynExpr.ArrayOrListOfSeqExpr (isArray, e, r) -> + | SynExpr.ArrayOrListComputed (isArray, e, r) -> rcheck Scope.ArrayOrList Collapse.Same r <| Range.modBoth (if isArray then 2 else 1) (if isArray then 2 else 1) r parseExpr e - | SynExpr.CompExpr (_arrayOrList, _, e, _r) as _c -> + | SynExpr.ComputationExpr (_, e, _r) as _c -> parseExpr e | SynExpr.ObjExpr (_, argOpt, bindings, extraImpls, newRange, wholeRange) as _objExpr -> match argOpt with diff --git a/src/fsharp/service/ServiceStructure.fsi b/src/fsharp/service/ServiceStructure.fsi index 3ed1eb0dbab..90271eb0fb7 100644 --- a/src/fsharp/service/ServiceStructure.fsi +++ b/src/fsharp/service/ServiceStructure.fsi @@ -25,7 +25,7 @@ module public Structure = | Member | LetOrUse | Val - | CompExpr + | ComputationExpr | IfThenElse | ThenInIfThenElse | ElseInIfThenElse diff --git a/src/fsharp/xlf/FSComp.txt.cs.xlf b/src/fsharp/xlf/FSComp.txt.cs.xlf index 4547e7196b0..39892964e72 100644 --- a/src/fsharp/xlf/FSComp.txt.cs.xlf +++ b/src/fsharp/xlf/FSComp.txt.cs.xlf @@ -132,6 +132,11 @@ implicitní yield + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation rozhraní s vícenásobným obecným vytvářením instancí @@ -477,11 +482,26 @@ Atributy nejde použít pro rozšíření typů. + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. Typy Byref nejsou v deklaraci otevřeného typu povolené. + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. Atribut InlineIfLambda je možné použít pouze u parametrů vložených funkcí metod s typem funkce nebo typem delegáta F#. @@ -512,6 +532,11 @@ use! se nedá kombinovat s and!. + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier Deklarace [<Literal>] nemůže používat aktivní vzor jako svůj identifikátor. @@ -3493,8 +3518,8 @@ - Invalid indexer expression - Neplatný výraz indexeru + Incomplete expression or invalid use of indexer syntax + Neplatný výraz indexeru diff --git a/src/fsharp/xlf/FSComp.txt.de.xlf b/src/fsharp/xlf/FSComp.txt.de.xlf index e334f315732..84738ccc8b6 100644 --- a/src/fsharp/xlf/FSComp.txt.de.xlf +++ b/src/fsharp/xlf/FSComp.txt.de.xlf @@ -132,6 +132,11 @@ implizite yield-Anweisung + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation Schnittstellen mit mehrfacher generischer Instanziierung @@ -477,11 +482,26 @@ Attribute können nicht auf Typerweiterungen angewendet werden. + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. Byref-Typen sind in einer Deklaration für offene Typen nicht zulässig. + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. Das "InlineIfLambda-Attribut" darf nur für Parameter von Inlinefunktionen von Methoden verwendet werden, deren Typ ein Funktions-oder F #-Delegattyp ist. @@ -512,6 +532,11 @@ "use!" darf nicht mit "and!" kombiniert werden. + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier Eine [<Literal>]-Deklaration kann kein aktives Muster für ihren Bezeichner verwenden. @@ -3493,8 +3518,8 @@ - Invalid indexer expression - Ungültiger Indexerausdruck. + Incomplete expression or invalid use of indexer syntax + Ungültiger Indexerausdruck. diff --git a/src/fsharp/xlf/FSComp.txt.es.xlf b/src/fsharp/xlf/FSComp.txt.es.xlf index 5731f13989c..87b8ad776f9 100644 --- a/src/fsharp/xlf/FSComp.txt.es.xlf +++ b/src/fsharp/xlf/FSComp.txt.es.xlf @@ -132,6 +132,11 @@ elemento yield implícito + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation interfaces con creación de instancias genéricas múltiples @@ -477,11 +482,26 @@ Los atributos no se pueden aplicar a las extensiones de tipo. + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. No se permiten tipos byref en una declaración de tipo abierto. + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. El atributo "InlineIfLambda" solo se puede usar en los parámetros de funciones insertadas de métodos cuyo tipo es una función o un tipo de delegado F#. @@ -512,6 +532,11 @@ No se puede combinar use! con and! + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier Una declaración [<Literal>] no puede usar un modelo activo para su identificador @@ -3493,8 +3518,8 @@ - Invalid indexer expression - Expresión de indizador no válido. + Incomplete expression or invalid use of indexer syntax + Expresión de indizador no válido. diff --git a/src/fsharp/xlf/FSComp.txt.fr.xlf b/src/fsharp/xlf/FSComp.txt.fr.xlf index da695b683a0..0fce2137838 100644 --- a/src/fsharp/xlf/FSComp.txt.fr.xlf +++ b/src/fsharp/xlf/FSComp.txt.fr.xlf @@ -132,6 +132,11 @@ yield implicite + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation interfaces avec plusieurs instanciations génériques @@ -477,11 +482,26 @@ Impossible d'appliquer des attributs aux extensions de type. + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. Les types Byref ne sont pas autorisés dans une déclaration de type ouverte. + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. L’attribut « InlineIfLambda » ne peut être utilisé que sur les paramètres des fonctions incorporées des méthodes dont le type est une fonction ou un type délégué F#. @@ -512,6 +532,11 @@ use! ne peut pas être combiné avec and! + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier Une déclaration [<Literal>] ne peut pas utiliser un modèle actif en tant qu'identificateur @@ -3493,8 +3518,8 @@ - Invalid indexer expression - Expression d'indexeur non valide + Incomplete expression or invalid use of indexer syntax + Expression d'indexeur non valide diff --git a/src/fsharp/xlf/FSComp.txt.it.xlf b/src/fsharp/xlf/FSComp.txt.it.xlf index 688bccc321f..ac8b50509da 100644 --- a/src/fsharp/xlf/FSComp.txt.it.xlf +++ b/src/fsharp/xlf/FSComp.txt.it.xlf @@ -132,6 +132,11 @@ istruzione yield implicita + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation interfacce con più creazioni di istanze generiche @@ -477,11 +482,26 @@ Gli attributi non possono essere applicati a estensioni di tipo. + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. I tipi byref non sono consentiti in una dichiarazione di tipo aperto. + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. L'attributo 'InlineIfLambda' può essere usato solo in parametri di funzioni impostate come inline di metodi il cui tipo è un tipo di funzione o delegato F#. @@ -512,6 +532,11 @@ Non è possibile combinare use! con and! + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier Una dichiarazione [<Literal>] non può usare un criterio attivo per il relativo identificatore @@ -3493,8 +3518,8 @@ - Invalid indexer expression - Espressione di indicizzatore non valida + Incomplete expression or invalid use of indexer syntax + Espressione di indicizzatore non valida diff --git a/src/fsharp/xlf/FSComp.txt.ja.xlf b/src/fsharp/xlf/FSComp.txt.ja.xlf index dd039326237..1fdf4047414 100644 --- a/src/fsharp/xlf/FSComp.txt.ja.xlf +++ b/src/fsharp/xlf/FSComp.txt.ja.xlf @@ -132,6 +132,11 @@ 暗黙的な yield + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation 複数のジェネリックのインスタンス化を含むインターフェイス @@ -477,11 +482,26 @@ 属性を型拡張に適用することはできません。 + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. Byref 型は、オープン型宣言では使用できません。 + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. 'InlineIfLambda' 属性を使用できるのは、型が関数または F# デリゲート型であるメソッドのインライン関数のパラメーターに対してのみです。 @@ -512,6 +532,11 @@ use! を and! と組み合わせて使用することはできません + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier [<Literal>] 宣言では、その識別子に対してアクティブ パターンを使用することはできません @@ -3493,8 +3518,8 @@ - Invalid indexer expression - インデクサー式が無効です + Incomplete expression or invalid use of indexer syntax + インデクサー式が無効です diff --git a/src/fsharp/xlf/FSComp.txt.ko.xlf b/src/fsharp/xlf/FSComp.txt.ko.xlf index f0b43c20eda..5f1e7f8a21e 100644 --- a/src/fsharp/xlf/FSComp.txt.ko.xlf +++ b/src/fsharp/xlf/FSComp.txt.ko.xlf @@ -132,6 +132,11 @@ 암시적 yield + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation 여러 제네릭 인스턴스화가 포함된 인터페이스 @@ -477,11 +482,26 @@ 형식 확장에 특성을 적용할 수 없습니다. + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. Byref 형식은 개방형 형식 선언에서 허용되지 않습니다. + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. 'InlineIfLambda' 특성은 형식이 함수 또는 F# 대리자 형식인 메서드의 인라인 함수 매개 변수에만 사용할 수 있습니다. @@ -512,6 +532,11 @@ use!는 and!와 함께 사용할 수 없습니다. + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier [<Literal>] 선언은 해당 식별자에 대한 활성 패턴을 사용할 수 없습니다. @@ -3493,8 +3518,8 @@ - Invalid indexer expression - 인덱서 식이 잘못되었습니다. + Incomplete expression or invalid use of indexer syntax + 인덱서 식이 잘못되었습니다. diff --git a/src/fsharp/xlf/FSComp.txt.pl.xlf b/src/fsharp/xlf/FSComp.txt.pl.xlf index 397c9ebb1bc..3b3961f96d8 100644 --- a/src/fsharp/xlf/FSComp.txt.pl.xlf +++ b/src/fsharp/xlf/FSComp.txt.pl.xlf @@ -132,6 +132,11 @@ niejawne słowo kluczowe yield + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation interfejsy z wieloma ogólnymi wystąpieniami @@ -477,11 +482,26 @@ Atrybutów nie można stosować do rozszerzeń typu. + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. Typy ByRef są niedozwolone w deklaracji typu otwartego. + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. Atrybut "InlineIfLambda" może być używany tylko w przypadku parametrów funkcji z podkreśleniem metod, których typ to funkcja lub typ delegata języka F #. @@ -512,6 +532,11 @@ Elementu use! nie można łączyć z elementem and! + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier Deklaracja [<Literal>] nie może używać aktywnego wzorca dla swojego identyfikatora @@ -3493,8 +3518,8 @@ - Invalid indexer expression - Nieprawidłowe wyrażenie indeksatora + Incomplete expression or invalid use of indexer syntax + Nieprawidłowe wyrażenie indeksatora diff --git a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf index 02e26fa5232..8d0fed3537a 100644 --- a/src/fsharp/xlf/FSComp.txt.pt-BR.xlf +++ b/src/fsharp/xlf/FSComp.txt.pt-BR.xlf @@ -132,6 +132,11 @@ yield implícito + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation interfaces com várias instanciações genéricas @@ -477,11 +482,26 @@ Os atributos não podem ser aplicados às extensões de tipo. + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. Os tipos Byref não são permitidos em uma declaração de tipo aberto. + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. O atributo 'InlineIfLambda' só pode ser usado em parâmetros de funções de métodos em linha cujo tipo seja uma função ou F# tipo delegado. @@ -512,6 +532,11 @@ use! não pode ser combinado com and! + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier Uma declaração [<Literal>] não pode usar um padrão ativo para seu identificador @@ -3493,8 +3518,8 @@ - Invalid indexer expression - Expressão de indexador inválida + Incomplete expression or invalid use of indexer syntax + Expressão de indexador inválida diff --git a/src/fsharp/xlf/FSComp.txt.ru.xlf b/src/fsharp/xlf/FSComp.txt.ru.xlf index 6608fadd7ad..8edc656379c 100644 --- a/src/fsharp/xlf/FSComp.txt.ru.xlf +++ b/src/fsharp/xlf/FSComp.txt.ru.xlf @@ -132,6 +132,11 @@ неявное использование yield + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation интерфейсы с множественным универсальным созданием экземпляра @@ -477,11 +482,26 @@ Атрибуты не могут быть применены к расширениям типа. + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. Типы ByRef запрещены в объявлении открытого типа. + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. Атрибут "InlineIfLambda" может использоваться только в параметрах встраиваемых функций методов, типом которых является функция или делегат F#. @@ -512,6 +532,11 @@ use! запрещено сочетать с and! + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier Объявление [<Literal>] не может использовать активный шаблон для своего идентификатора. @@ -3493,8 +3518,8 @@ - Invalid indexer expression - Недопустимое выражение индексатора + Incomplete expression or invalid use of indexer syntax + Недопустимое выражение индексатора diff --git a/src/fsharp/xlf/FSComp.txt.tr.xlf b/src/fsharp/xlf/FSComp.txt.tr.xlf index c60bd9c2519..b5e5afa7bd9 100644 --- a/src/fsharp/xlf/FSComp.txt.tr.xlf +++ b/src/fsharp/xlf/FSComp.txt.tr.xlf @@ -132,6 +132,11 @@ örtük yield + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation birden çok genel örnek oluşturma içeren arabirimler @@ -477,11 +482,26 @@ Öznitelikler tür uzantılarına uygulanamaz. + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. Açık tür bildiriminde Byref türlerine izin verilmez. + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. 'InlineIfLambda' özniteliği yalnızca işlev veya F# temsilci türündeki yöntemlerin satır içine alınmış işlev parametrelerinde kullanılabilir. @@ -512,6 +532,11 @@ use!, and! ile birleştirilemez + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier [<Literal>] bildirimi, tanımlayıcısı için etkin desen kullanamaz @@ -3493,8 +3518,8 @@ - Invalid indexer expression - Geçersiz dizin erişimcisi ifadesi + Incomplete expression or invalid use of indexer syntax + Geçersiz dizin erişimcisi ifadesi diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf index 8ce021f51fa..bf4125cff3d 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hans.xlf @@ -132,6 +132,11 @@ 隐式 yield + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation 具有多个泛型实例化的接口 @@ -477,11 +482,26 @@ 属性不可应用于类型扩展。 + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. 在开放类型声明中不允许使用 Byref 类型。 + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. "InlineIfLambda" 特性只能用于类型为函数或 F# 委托类型的方法的内联函数的参数。 @@ -512,6 +532,11 @@ use! 不得与 and! 结合使用 + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier [<Literal>] 声明不能对其标识符使用活动模式 @@ -3493,8 +3518,8 @@ - Invalid indexer expression - 索引器表达式无效 + Incomplete expression or invalid use of indexer syntax + 索引器表达式无效 diff --git a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf index 332e88537be..6a90ea5769f 100644 --- a/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/fsharp/xlf/FSComp.txt.zh-Hant.xlf @@ -132,6 +132,11 @@ 隱含 yield + + revised index and slicing notation + revised index and slicing notation + + interfaces with multiple generic instantiation 具有多個泛型具現化的介面 @@ -477,11 +482,26 @@ 屬性無法套用到類型延伸模組。 + + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + + + + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + + Byref types are not allowed in an open type declaration. 開放式類型宣告中不允許 Byref 類型。 + + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + The syntax 'arr.[idx]' is now revised to 'arr[idx]'. Please update your code. + + The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type. 'InlineIfLambda' 屬性只能用於類型為函式或 F# 委派類型之方法的內嵌函式參數。 @@ -512,6 +532,11 @@ use! 不可與 and! 合併 + + Invalid use of reverse index in list expression. + Invalid use of reverse index in list expression. + + A [<Literal>] declaration cannot use an active pattern for its identifier [<Literal>] 宣告不能對其識別碼使用現用模式 @@ -3493,8 +3518,8 @@ - Invalid indexer expression - 無效的索引子運算式 + Incomplete expression or invalid use of indexer syntax + 無效的索引子運算式 diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalAnalysis/Comments.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalAnalysis/Comments.fs index 0410f5cc3e4..e378a70aaeb 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalAnalysis/Comments.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalAnalysis/Comments.fs @@ -20,7 +20,7 @@ module Comments = |> ignore // This test was automatically generated (moved from FSharpQA suite - Conformance/LexicalAnalysis/Comments) - //Unexpected symbol '\*' in implementation file$ + [] let ``Comments - E_star02.fs - --test:ErrorRanges`` compilation = compilation @@ -29,7 +29,7 @@ module Comments = |> compile |> shouldFail |> withErrorCode 0010 - |> withDiagnosticMessageMatches "Unexpected symbol '\*' in implementation file$" + |> withDiagnosticMessageMatches @"Unexpected symbol '\)' in implementation file$" |> ignore // This test was automatically generated (moved from FSharpQA suite - Conformance/LexicalAnalysis/Comments) diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/SuggestionsTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/SuggestionsTests.fs index 85a5dbf6dbb..718dd8fed57 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/SuggestionsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/SuggestionsTests.fs @@ -189,7 +189,6 @@ let a = (f())[1] |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3217, Line 3, Col 9, Line 3, Col 10, "This value is not a function and cannot be applied. Did you intend to access the indexer via d.[index] instead?") (Error 3, Line 5, Col 9, Line 5, Col 10, "This value is not a function and cannot be applied.") (Error 3217, Line 8, Col 10, Line 8, Col 13, "This expression is not a function and cannot be applied. Did you intend to access the indexer via expr.[index] instead?")] diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/WrongSyntaxInForLoop.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/WrongSyntaxInForLoop.fs index 037624160a1..774ac1fda65 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/WrongSyntaxInForLoop.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/WrongSyntaxInForLoop.fs @@ -8,7 +8,7 @@ open FSharp.Test.Compiler module ``Wrong syntax in for loop`` = - [] + [] let ``Equals instead of in``() = FSharp """ module X diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index e091a389cd9..8576a44d1ab 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -716,7 +716,7 @@ module rec Compiler = match result with | Success r | Failure r -> if not <| diagnosticMatches pattern r.Diagnostics then - failwith "Expected diagnostic message pattern was not found in compilation diagnostics." + failwithf "Expected diagnostic message pattern was not found in compilation diagnostics.\nDiagnostics:\n%A" r.Diagnostics result let withDiagnosticMessageDoesntMatch (pattern: string) (result: TestResult) : TestResult = diff --git a/tests/fsharp/tests.fs b/tests/fsharp/tests.fs index 1fb5f522256..9902aa8aad8 100644 --- a/tests/fsharp/tests.fs +++ b/tests/fsharp/tests.fs @@ -59,13 +59,40 @@ module CoreTests = let ``apporder-FSI_BASIC`` () = singleTestBuildAndRun "core/apporder" FSI_BASIC [] - let ``array-FSC_BASIC_OPT_MINUS`` () = singleTestBuildAndRun "core/array" FSC_BASIC_OPT_MINUS + let ``array-FSC_BASIC_OPT_MINUS-5.0`` () = singleTestBuildAndRunVersion "core/array" FSC_BASIC_OPT_MINUS "5.0" [] - let ``array-FSC_BASIC`` () = singleTestBuildAndRun "core/array" FSC_BASIC + let ``array-FSC_BASIC-5.0`` () = singleTestBuildAndRunVersion "core/array" FSC_BASIC "5.0" [] - let ``array-FSI_BASIC`` () = singleTestBuildAndRun "core/array" FSI_BASIC + let ``array-FSI_BASIC-5.0`` () = singleTestBuildAndRunVersion "core/array" FSI_BASIC "5.0" + + [] + let ``array-FSC_BASIC-preview`` () = singleTestBuildAndRunVersion "core/array" FSC_BASIC "preview" + + [] + let ``array-no-dot-FSC_BASIC_OPT_MINUS`` () = singleTestBuildAndRunVersion "core/array-no-dot" FSC_BASIC_OPT_MINUS "preview" + + [] + let ``array-no-dot-FSC_BASIC`` () = singleTestBuildAndRunVersion "core/array-no-dot" FSC_BASIC "preview" + + [] + let ``array-no-dot-FSI_BASIC`` () = singleTestBuildAndRunVersion "core/array-no-dot" FSI_BASIC "preview" + + [] + let ``array-no-dot-warnings-langversion-default`` () = + let cfg = testConfig "core/array-no-dot-warnings" + singleVersionedNegTest cfg "default" "test-langversion-default" + + [] + let ``array-no-dot-warnings-langversion-5_0`` () = + let cfg = testConfig "core/array-no-dot-warnings" + singleVersionedNegTest cfg "5.0" "test-langversion-5.0" + + [] + let ``array-no-dot-warnings-langversion-preview`` () = + let cfg = testConfig "core/array-no-dot-warnings" + singleVersionedNegTest cfg "preview" "test-langversion-preview" [] let ``comprehensions-FSC_BASIC_OPT_MINUS`` () = singleTestBuildAndRun "core/comprehensions" FSC_BASIC_OPT_MINUS @@ -3164,6 +3191,9 @@ module GeneratedSignatureTests = [] let ``array-GENERATED_SIGNATURE``() = singleTestBuildAndRun "core/array" GENERATED_SIGNATURE + [] + let ``array-no-dot-GENERATED_SIGNATURE``() = singleTestBuildAndRunVersion "core/array-no-dot-" GENERATED_SIGNATURE "preview" + [] let ``genericmeasures-GENERATED_SIGNATURE`` () = singleTestBuildAndRun "core/genericmeasures" GENERATED_SIGNATURE diff --git a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/CodeGenRenamings01.il.bsl b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/CodeGenRenamings01.il.bsl index 08a6e0020c2..8ca2b152444 100644 --- a/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/CodeGenRenamings01.il.bsl +++ b/tests/fsharpqa/Source/CodeGen/EmittedIL/Misc/CodeGenRenamings01.il.bsl @@ -471,7 +471,6 @@ IL_0038: dup IL_0039: stsfld int32[] ''.$CodeGenRenamings01::array@6 IL_003e: stloc.1 - .line 7,7 : 1,27 '' IL_003f: ldc.i4.1 IL_0040: ldc.i4.1 IL_0041: ldc.i4.s 10 diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/flaterrors/E_MultiLine01.fs b/tests/fsharpqa/Source/CompilerOptions/fsc/flaterrors/E_MultiLine01.fs index b2c362464ac..fcb5e10f2ae 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/flaterrors/E_MultiLine01.fs +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/flaterrors/E_MultiLine01.fs @@ -1,6 +1,6 @@ // #Regression #NoMT #CompilerOptions #RequiresENU // Test that without [--flaterrors] flag multi-line errors are emitted in a regular way, i.e. spanned to more that one line -//This expression was expected to have type +//This expression was expected to have type // ''a list' //but here has type // 'seq<'b>' diff --git a/tests/fsharpqa/Source/CompilerOptions/fsc/flaterrors/E_MultiLine02.fs b/tests/fsharpqa/Source/CompilerOptions/fsc/flaterrors/E_MultiLine02.fs index 8bcc6e508ac..511987567fc 100644 --- a/tests/fsharpqa/Source/CompilerOptions/fsc/flaterrors/E_MultiLine02.fs +++ b/tests/fsharpqa/Source/CompilerOptions/fsc/flaterrors/E_MultiLine02.fs @@ -1,5 +1,5 @@ // #Regression #NoMT #CompilerOptions // Test that using [--flaterrors] flag multi-line errors are flattened, i.e. concatenated into one-line error message. -//This expression was expected to have type. ''a list' .but here has type. 'seq<'b>' +//This expression was expected to have type. ''a list' .but here has type. 'seq<'b>' List.rev {1..10} |> ignore diff --git a/tests/fsharpqa/Source/Diagnostics/General/E_ThisValueIsNotAFunctionAndCannotBeApplied01.fs b/tests/fsharpqa/Source/Diagnostics/General/E_ThisValueIsNotAFunctionAndCannotBeApplied01.fs deleted file mode 100644 index cf15f433544..00000000000 --- a/tests/fsharpqa/Source/Diagnostics/General/E_ThisValueIsNotAFunctionAndCannotBeApplied01.fs +++ /dev/null @@ -1,7 +0,0 @@ -// #Regression #Diagnostics -// Regression test for FSHARP1.0:1406 -// - - - -let foo (arr : int[,]) = arr[1,2] diff --git a/tests/fsharpqa/Source/Diagnostics/General/env.lst b/tests/fsharpqa/Source/Diagnostics/General/env.lst index a249196a5b0..d77d0099a55 100644 --- a/tests/fsharpqa/Source/Diagnostics/General/env.lst +++ b/tests/fsharpqa/Source/Diagnostics/General/env.lst @@ -88,8 +88,6 @@ NoMT SOURCE=E_MissingSourceFile04.fs SCFLAGS="--exec doesnotexist.fs" FSIMODE=PI SOURCE=E_IncompleteConstruct01.fs # E_IncompleteConstruct01.fs SOURCE=E_IncompleteConstruct01b.fs # E_IncompleteConstruct01b.fs - SOURCE=E_ThisValueIsNotAFunctionAndCannotBeApplied01.fs SCFLAGS="--test:ErrorRanges" # E_ThisValueIsNotAFunctionAndCannotBeApplied01.fs - SOURCE=E_UnexpectedKeyworkWith01.fs SCFLAGS="--test:ErrorRanges" # E_UnexpectedKeyworkWith01.fs SOURCE=E_MemberObjectctorTakeGiven.fs # E_MemberObjectctorTakeGiven.fs SOURCE=E_StructMustHaveAtLeastOneField.fs SCFLAGS="--test:ErrorRanges" # E_StructMustHaveAtLeastOneField.fs diff --git a/tests/fsharpqa/Source/InteractiveSession/Misc/E_RangeOperator01.fsx b/tests/fsharpqa/Source/InteractiveSession/Misc/E_RangeOperator01.fsx index 004ef985471..8f3bdfa834e 100644 --- a/tests/fsharpqa/Source/InteractiveSession/Misc/E_RangeOperator01.fsx +++ b/tests/fsharpqa/Source/InteractiveSession/Misc/E_RangeOperator01.fsx @@ -3,7 +3,7 @@ //fsbug //nonTerminalId\.GetTag -//Unexpected symbol '\.\.' in interaction\. Expected incomplete structured construct at or before this point, ';', ';;' or other token\.$ +//Incomplete expression or invalid use of indexer syntax aaaa..;; diff --git a/tests/service/EditorTests.fs b/tests/service/EditorTests.fs index e3bc5f7d23e..95eb47bac96 100644 --- a/tests/service/EditorTests.fs +++ b/tests/service/EditorTests.fs @@ -655,18 +655,8 @@ let _ = arr.[..number2] ("val number2", (3, 13, 3, 20)) ("val number1", (3, 4, 3, 11)) ("val arr", (4, 8, 4, 11)) - ("Microsoft", (4, 11, 4, 12)) - ("OperatorIntrinsics", (4, 11, 4, 12)) - ("Operators", (4, 11, 4, 12)) - ("Core", (4, 11, 4, 12)) - ("FSharp", (4, 11, 4, 12)) ("val number1", (4, 16, 4, 23)) ("val arr", (5, 8, 5, 11)) - ("Microsoft", (5, 11, 5, 12)) - ("OperatorIntrinsics", (5, 11, 5, 12)) - ("Operators", (5, 11, 5, 12)) - ("Core", (5, 11, 5, 12)) - ("FSharp", (5, 11, 5, 12)) ("val number2", (5, 15, 5, 22)) ("Test", (1, 0, 1, 0))|] diff --git a/vsintegration/src/FSharp.Editor/Structure/BlockStructureService.fs b/vsintegration/src/FSharp.Editor/Structure/BlockStructureService.fs index 8211b8f4bc2..4f93f75dca6 100644 --- a/vsintegration/src/FSharp.Editor/Structure/BlockStructureService.fs +++ b/vsintegration/src/FSharp.Editor/Structure/BlockStructureService.fs @@ -23,7 +23,7 @@ module internal BlockStructure = | Scope.Interface | Scope.TypeExtension | Scope.RecordDefn - | Scope.CompExpr + | Scope.ComputationExpr | Scope.ObjExpr | Scope.UnionDefn | Scope.Attribute @@ -84,7 +84,7 @@ module internal BlockStructure = | Scope.Interface | Scope.TypeExtension | Scope.RecordDefn - | Scope.CompExpr + | Scope.ComputationExpr | Scope.ObjExpr | Scope.UnionDefn | Scope.Type diff --git a/vsintegration/tests/Salsa/salsa.fs b/vsintegration/tests/Salsa/salsa.fs index 523123e01b6..e63bce98029 100644 --- a/vsintegration/tests/Salsa/salsa.fs +++ b/vsintegration/tests/Salsa/salsa.fs @@ -18,6 +18,7 @@ open System.Text open System.Collections.Generic open System.Runtime.InteropServices open System.Threading +open System.Threading.Tasks open Microsoft.VisualStudio open Microsoft.VisualStudio.Shell.Interop open Microsoft.VisualStudio.FSharp.ProjectSystem @@ -34,6 +35,19 @@ module internal Salsa = exception MarkerNotFoundException of string + type Async with + static member RunImmediate (computation: Async<'T>, ?cancellationToken ) = + let cancellationToken = defaultArg cancellationToken Async.DefaultCancellationToken + let ts = TaskCompletionSource<'T>() + let task = ts.Task + Async.StartWithContinuations( + computation, + (fun k -> ts.SetResult k), + (fun exn -> ts.SetException exn), + (fun _ -> ts.SetCanceled()), + cancellationToken) + task.Result + type HostCompile() = let mutable capturedFlags = null let mutable capturedSources = null From 695ffa4fc69f48f7df4e983507ec1c62bf18c638 Mon Sep 17 00:00:00 2001 From: Don Syme Date: Tue, 27 Jul 2021 14:52:24 +0100 Subject: [PATCH 2/2] add tests --- .../test-langversion-5.0.bsl | 4 + .../test-langversion-5.0.fsx | 9 + .../test-langversion-default.bsl | 14 + .../test-langversion-default.fsx | 9 + .../test-langversion-preview.bsl | 14 + .../test-langversion-preview.fsx | 9 + tests/fsharp/core/array-no-dot/test.fsx | 1347 +++++++++++++++++ 7 files changed, 1406 insertions(+) create mode 100644 tests/fsharp/core/array-no-dot-warnings/test-langversion-5.0.bsl create mode 100644 tests/fsharp/core/array-no-dot-warnings/test-langversion-5.0.fsx create mode 100644 tests/fsharp/core/array-no-dot-warnings/test-langversion-default.bsl create mode 100644 tests/fsharp/core/array-no-dot-warnings/test-langversion-default.fsx create mode 100644 tests/fsharp/core/array-no-dot-warnings/test-langversion-preview.bsl create mode 100644 tests/fsharp/core/array-no-dot-warnings/test-langversion-preview.fsx create mode 100644 tests/fsharp/core/array-no-dot/test.fsx diff --git a/tests/fsharp/core/array-no-dot-warnings/test-langversion-5.0.bsl b/tests/fsharp/core/array-no-dot-warnings/test-langversion-5.0.bsl new file mode 100644 index 00000000000..8513a2590bc --- /dev/null +++ b/tests/fsharp/core/array-no-dot-warnings/test-langversion-5.0.bsl @@ -0,0 +1,4 @@ + +test-langversion-5.0.fsx(9,18,9,21): typecheck error FS0001: The type 'float' does not match the type 'int' + +test-langversion-5.0.fsx(9,16,9,17): typecheck error FS0043: The type 'float' does not match the type 'int' diff --git a/tests/fsharp/core/array-no-dot-warnings/test-langversion-5.0.fsx b/tests/fsharp/core/array-no-dot-warnings/test-langversion-5.0.fsx new file mode 100644 index 00000000000..0932d8afb20 --- /dev/null +++ b/tests/fsharp/core/array-no-dot-warnings/test-langversion-5.0.fsx @@ -0,0 +1,9 @@ +let f1 a = () +let f2 a b = () + +let v1 = f1[1] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview +let v2 = f2[1][2] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview +let v3 = f2 [1][2] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview +let v4 = f2 (id [1])[2] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview + +let _error = 1 + 1.0 \ No newline at end of file diff --git a/tests/fsharp/core/array-no-dot-warnings/test-langversion-default.bsl b/tests/fsharp/core/array-no-dot-warnings/test-langversion-default.bsl new file mode 100644 index 00000000000..cc402d8a349 --- /dev/null +++ b/tests/fsharp/core/array-no-dot-warnings/test-langversion-default.bsl @@ -0,0 +1,14 @@ + +test-langversion-default.fsx(4,10,4,15): typecheck error FS3367: The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + +test-langversion-default.fsx(5,10,5,15): typecheck error FS3367: The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + +test-langversion-default.fsx(5,10,5,18): typecheck error FS3367: The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + +test-langversion-default.fsx(6,10,6,19): typecheck error FS3367: The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + +test-langversion-default.fsx(7,10,7,24): typecheck error FS3367: The syntax 'expr1[expr2]' is now reserved for indexing and slicing. If you intend indexing or slicing then enable '--langversion:preview' or use 'expr1.[expr2]'. If you intend multiple arguments to a function, then specify an explicit `--langversion` before 6.0, or add a space between arguments 'someFunction expr1 [expr2]'. + +test-langversion-default.fsx(9,18,9,21): typecheck error FS0001: The type 'float' does not match the type 'int' + +test-langversion-default.fsx(9,16,9,17): typecheck error FS0043: The type 'float' does not match the type 'int' diff --git a/tests/fsharp/core/array-no-dot-warnings/test-langversion-default.fsx b/tests/fsharp/core/array-no-dot-warnings/test-langversion-default.fsx new file mode 100644 index 00000000000..0932d8afb20 --- /dev/null +++ b/tests/fsharp/core/array-no-dot-warnings/test-langversion-default.fsx @@ -0,0 +1,9 @@ +let f1 a = () +let f2 a b = () + +let v1 = f1[1] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview +let v2 = f2[1][2] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview +let v3 = f2 [1][2] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview +let v4 = f2 (id [1])[2] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview + +let _error = 1 + 1.0 \ No newline at end of file diff --git a/tests/fsharp/core/array-no-dot-warnings/test-langversion-preview.bsl b/tests/fsharp/core/array-no-dot-warnings/test-langversion-preview.bsl new file mode 100644 index 00000000000..7e56ad04e10 --- /dev/null +++ b/tests/fsharp/core/array-no-dot-warnings/test-langversion-preview.bsl @@ -0,0 +1,14 @@ + +test-langversion-preview.fsx(4,10,4,15): typecheck error FS3365: The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + +test-langversion-preview.fsx(5,10,5,15): typecheck error FS3365: The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + +test-langversion-preview.fsx(5,10,5,18): typecheck error FS3365: The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + +test-langversion-preview.fsx(6,10,6,19): typecheck error FS3365: The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + +test-langversion-preview.fsx(7,10,7,24): typecheck error FS3365: The syntax 'expr1[expr2]' is used for indexing and slicing. Consider adding a type annotation or, if two function arguments are intended, then add a space, e.g. 'someFunction expr1 [expr2]'. + +test-langversion-preview.fsx(9,18,9,21): typecheck error FS0001: The type 'float' does not match the type 'int' + +test-langversion-preview.fsx(9,16,9,17): typecheck error FS0043: The type 'float' does not match the type 'int' diff --git a/tests/fsharp/core/array-no-dot-warnings/test-langversion-preview.fsx b/tests/fsharp/core/array-no-dot-warnings/test-langversion-preview.fsx new file mode 100644 index 00000000000..0932d8afb20 --- /dev/null +++ b/tests/fsharp/core/array-no-dot-warnings/test-langversion-preview.fsx @@ -0,0 +1,9 @@ +let f1 a = () +let f2 a b = () + +let v1 = f1[1] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview +let v2 = f2[1][2] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview +let v3 = f2 [1][2] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview +let v4 = f2 (id [1])[2] // with langversion 'default' or 'latest' enabled this should give a warning saying to add a space or enable preview + +let _error = 1 + 1.0 \ No newline at end of file diff --git a/tests/fsharp/core/array-no-dot/test.fsx b/tests/fsharp/core/array-no-dot/test.fsx new file mode 100644 index 00000000000..5aaac61fdfb --- /dev/null +++ b/tests/fsharp/core/array-no-dot/test.fsx @@ -0,0 +1,1347 @@ +// #Conformance #Arrays #Stress #Structs #Mutable #ControlFlow #LetBindings +#if TESTS_AS_APP +module Core_array +#endif + +let mutable failures = [] +let report_failure (s) = + stderr.WriteLine " NO"; failures <- s :: failures +let test s b = if not b then (stderr.Write(s:string); report_failure(s) ) +let check s b1 b2 = test s (b1 = b2) + + +(* TEST SUITE FOR Array *) + +let test_make_get_set_length () = + let arr = Array.create 3 0 in + test "fewoih" (Array.get arr 0 = 0); + test "vvrew0" (Array.get arr 2 = 0); + ignore (Array.set arr 0 4); + test "vsdiuvs" (Array.get arr 0 = 4); + test "vropivrwe" (Array.length arr = 3) + +let test_const () = + let arr = [| 4;3;2 |] in + test "sdvjk2" (Array.get arr 0 = 4); + test "cedkj" (Array.get arr 2 = 2); + ignore (Array.set arr 0 4); + test "ds9023" (Array.get arr 0 = 4); + test "sdio2" (Array.length arr = 3) + +let test_const_empty () = + let arr = [| |] in + test "sdio2" (Array.length arr = 0) + +let test_map () = + let arr = Array.map (fun x -> x + 1) ( [| 4;3;2 |]) in + test "test2927: sdvjk2" (Array.get arr 0 = 5); + test "test2927: cedkj" (Array.get arr 2 = 3) + +let test_iter () = + Array.iter (fun x -> test "fuo" (x <= 4)) ( [| 4;3;2 |]) + +let test_iteri () = + let arr = [| 4;3;2 |] in + Array.iteri (fun i x -> test "fuo" (arr.[i] = x)) arr + +let test_mapi () = + let arr = [| 4;3;2 |] in + let arr2 = Array.mapi (fun i x -> test "dwqfuo" (arr.[i] = x); i + x) arr in + test "test2927: sdvjk2" (Array.get arr2 0 = 4); + test "test2927: cedkj" (Array.get arr2 2 = 4) + +let test_isEmpty () = + test "isEmpty a" (Array.isEmpty [||]) + test "isEmpty b" (Array.isEmpty <| Array.create 0 42) + test "isEmpty c" <| not (Array.isEmpty <| [| 1 |]) + test "isEmpty d" (Array.isEmpty <| Array.empty) + +let test_create () = + let arr = Array.create 10 10 + for i in 0 .. 9 do + test "test_create" (arr.[i] = 10) + +let test_concat () = + let make n = [| for i in n .. n + 9 -> i |] + let arr = [| for i in 0..+10..50 -> make i|] + test "concat a" (Array.concat arr = [|0..59|]) + + let arr2 = [| for i in 0..50 -> [||] |] + test "concat b" (Array.concat arr2 = [| |]) + + let arr3 = [| [||]; [||]; [|1; 2|]; [||] |] + test "concat c" (Array.concat arr3 = [|1; 2|]) + +let test_sub () = + test "sub a" (Array.sub [|0..100|] 10 20 = [|10..29|]) + test "sub b" (Array.sub [|0..100|] 0 101 = [|0..100|]) + test "sub c" (Array.sub [|0..100|] 0 1 = [|0|]) + test "sub d" (Array.sub [|0..100|] 0 0 = [||]) + +let test_fold2 () = + test "fold2 a" + (Array.fold2 (fun i j k -> i+j+k) 100 [|1;2;3|] [|1;2;3|] = 112) + + test "fold2_b" + (Array.fold2 (fun i j k -> i-j-k) 100 [|1;2;3|] [|1;2;3|] = 100-12) + +let test_foldBack2 () = + test "foldBack2 a" + (Array.foldBack2 (fun i j k -> i+j+k) [|1;2;3|] [|1;2;3|] 100 = 112) + + test "foldBack2_b" + (Array.foldBack2 (fun i j k -> k-i-j) [|1;2;3|] [|1;2;3|] 100 = 100-12) + +let test_scan () = + test "scan" + (Array.scan (+) 0 [|1..5|] = [|0; 1; 3; 6; 10; 15|]) + + test "scanBack" + (Array.scanBack (+) [|1..5|] 0 = [|15; 14; 12; 9; 5; 0|]) + +let test_iter2 () = + let c = ref -1 + Array.iter2 (fun x y -> incr c; test "iter2" (!c = x && !c = y)) [|0..100|] [|0..100|] + test "iter2" (!c = 100) + +let test_iteri2 () = + let c = ref 0 + Array.iteri2 (fun i j k -> c := !c+i+j+k) [|1;2;3|] [|10;20;30|] + test "iteri2" (!c = 6+60+3) + +let test_map2 () = + test "map2" + (Array.map2 (+) [|0..100|] [|0..100|] = [|0..+2..200|]) + +let test_mapi2 () = + test "mapi2 a" + (Array.mapi2 (fun i j k -> i+j+k) [|1..10|] [|1..10|] = [|2..+3..29|]) + + test "mapi2_b" + (try Array.mapi2 (fun i j k -> i+j+k) [||] [|1..10|] |> ignore; false + with _ -> true) + +let test_exists () = + test "exists a" + ([|1..100|] |> Array.exists ((=) 50)) + + test "exists b" <| not + ([|1..100|] |> Array.exists ((=) 150)) + +let test_forall () = + test "forall a" + ([|1..100|] |> Array.forall (fun x -> x < 150)) + + test "forall b" <| not + ([|1..100|] |> Array.forall (fun x -> x < 80)) + +let test_exists2 () = + test "exists2 a" <| Array.exists2 (=) + [|1; 2; 3; 4; 5; 6|] + [|2; 3; 4; 5; 6; 6|] + + test "exists2 b" <| not (Array.exists2 (=) + [|1; 2; 3; 4; 5; 6|] + [|2; 3; 4; 5; 6; 7|]) + +let test_forall2 () = + test "forall2 a" + (Array.forall2 (=) [|1..10|] [|1..10|]) + + test "forall2_b" <| not + (Array.forall2 (=) [|1;2;3;4;5|] [|1;2;3;0;5|]) + +let test_filter () = + test "filter a" + (Array.filter (fun x -> x % 2 = 0) [|0..100|] = [|0..+2..100|]) + + test "filter b" + (Array.filter (fun x -> false) [|0..100|] = [||]) + + test "filter c" + (Array.filter (fun x -> true) [|0..100|] = [|0..100|]) + + +let test_partition () = + let p1, p2 = Array.partition (fun x -> x % 2 = 0) [|0..100|] + test "partition" + (p1 = [|0..+2..100|] && p2 = [|1..+2..100|]) + +let test_choose () = + test "choose" + (Array.choose (fun x -> if x % 2 = 0 then Some (x/2) else None) [|0..100|] = [|0..50|]) + +let test_find () = + test "find a" + ([|1..100|] |> Array.find (fun x -> x > 50) = 51) + + test "find b" + (try [|1..100|] |> Array.find (fun x -> x > 180) |> ignore; false + with _ -> true) + +module Array = + let findIndexi f (array : array<_>) = + let len = array.Length + let rec go n = + if n >= len then + failwith "fail" + elif f n array.[n] then + n + else + go (n+1) + go 0 + + let tryFindIndexi f (array : array<_>) = + let len = array.Length + let rec go n = if n >= len then None elif f n array.[n] then Some n else go (n+1) + go 0 + +let test_findIndex () = + test "findIndex a" + (Array.findIndex (fun i -> i >= 4) [|0..10|] = 4) + + test "findIndex b" + (try Array.findIndex (fun i -> i >= 20) [|0..10|] |> ignore; false + with _ -> true) + + test "findIndexi a" + (Array.findIndexi (=) [|1; 2; 3; 3; 2; 1|] = 3) + + test "findIndexi b" + (try Array.findIndexi (=) [|1..10|] |> ignore; false + with _ -> true) + +let test_tryfind () = + test "tryFind" + ([|1..100|] |> Array.tryFind (fun x -> x > 50) = Some 51) + + test "tryFind b" + ([|1..100|] |> Array.tryFind (fun x -> x > 180) = None) + + test "tryfind_index a" + (Array.tryFindIndex (fun x -> x = 4) [|0..10|] = Some 4) + + test "tryfind_index b" + (Array.tryFindIndex (fun x -> x = 42) [|0..10|] = None) + + test "tryFindIndexi a" + (Array.tryFindIndexi (=) [|1;2;3;4;4;3;2;1|] = Some 4) + + test "tryFindIndexi b" + (Array.tryFindIndexi (=) [|1..10|] = None) + +let test_first () = + test "first a" + ([|1..100|] |> Array.tryPick (fun x -> if x > 50 then Some (x*x) else None) = Some (51*51)) + + test "first b" + ([|1..100|] |> Array.tryPick (fun x -> None) = None) + + test "first c" + ([||] |> Array.tryPick (fun _ -> Some 42) = None) + +let test_sort () = + + test "sort a" (Array.sort [||] = [||]) + test "sort b" (Array.sort [|1|] = [|1|]) + test "sort c" (Array.sort [|1;2|] = [|1;2|]) + test "sort d" (Array.sort [|2;1|] = [|1;2|]) + test "sort e" (Array.sort [|1..1000|] = [|1..1000|]) + test "sort f" (Array.sort [|1000..-1..1|] = [|1..1000|]) + +let test_sort_by () = + + test "Array.sortBy a" (Array.sortBy int [||] = [||]) + test "Array.sortBy b" (Array.sortBy int [|1|] = [|1|]) + test "Array.sortBy c" (Array.sortBy int [|1;2|] = [|1;2|]) + test "Array.sortBy d" (Array.sortBy int [|2;1|] = [|1;2|]) + test "Array.sortBy e" (Array.sortBy int [|1..1000|] = [|1..1000|]) + test "Array.sortBy f" (Array.sortBy int [|1000..-1..1|] = [|1..1000|]) + + let testGen s f = + test ("Array.sortBy a "+s) (Array.sortBy f [||] = [||]) + test ("Array.sortBy b "+s) (Array.sortBy f [|1|] = [|1|]) + test ("Array.sortBy c "+s) (Array.sortBy f [|1;2|] = [|1;2|]) + test ("Array.sortBy d "+s) (Array.sortBy f [|2;1|] = [|1;2|]) + test ("Array.sortBy e "+s) (Array.sortBy f [|1..1000|] = [|1..1000|]) + test ("Array.sortBy f "+s) (Array.sortBy f [|1000..-1..1|] = [|1..1000|]) + + // All these projects from integers preserve the expected key ordering for the tests in 'testGen()' + testGen "int" int + testGen "uint32" uint32 + testGen "int16" int16 + testGen "uint16" uint16 + testGen "int64" int64 + testGen "uint64" uint64 + testGen "nativeint" nativeint + testGen "unativeint" unativeint + testGen "float" float + testGen "float32" float32 + testGen "decimal" decimal + + test "Array.sortBy g" (Array.sortBy int [|"4";"2";"3";"1";"5"|] = [|"1";"2";"3";"4";"5"|]) + test "Array.sortBy h" (Array.sortBy abs [|1;-2;5;-4;0;-6;3|] = [|0;1;-2;3;-4;5;-6|]) + test "Array.sortBy i" (Array.sortBy String.length [|"a";"abcd";"ab";"";"abc"|] = [|"";"a";"ab";"abc";"abcd"|]) + + +let test_list_stableSortBy() = + for lo in 0 .. 100 do + for hi in lo .. 100 do + test (sprintf "vre9u0rejkn, lo = %d, hi = %d" lo hi) (List.sortBy snd [ for i in lo .. hi -> (i, i % 17) ] = [ for key in 0 .. 16 do for i in lo .. hi do if i % 17 = key then yield (i, i % 17) ]) + +test_list_stableSortBy() + + +[] +type Key = + | Key of int * int + interface System.IComparable with + member x.CompareTo(yobj:obj) = + match yobj with + | :? Key as y -> + let (Key(y1,y2)) = y in + let (Key(x1,x2)) = x in + compare x2 y2 + | _ -> failwith "failure" + + override x.Equals(yobj) = + match yobj with + | :? Key as y -> + let (Key(y1,y2)) = y in + let (Key(x1,x2)) = x in + x2 = y2 + | _ -> false + + override x.GetHashCode() = + let (Key(x1,x2)) = x in + hash x2 + +let test_list_stableSort() = + for lo in 0 .. 100 do + for hi in lo .. 100 do + test (sprintf "vre9u0rejkn, lo = %d, hi = %d" lo hi) (List.sort [ for i in lo .. hi -> Key(i, i % 17) ] = [ for key in 0 .. 16 do for i in lo .. hi do if i % 17 = key then yield Key(i, i % 17) ]) + +test_list_stableSort() + +let test_list_stableSortByNonIntegerKey() = + for lo in 0 .. 100 do + for hi in lo .. 100 do + test (sprintf "vre9u0rejkn, lo = %d, hi = %d" lo hi) (List.sortBy (fun (Key(a,b)) -> Key(0,b)) [ for i in lo .. hi -> Key(i, i % 17) ] = [ for key in 0 .. 16 do for i in lo .. hi do if i % 17 = key then yield Key(i, i % 17) ]) + +test_list_stableSortByNonIntegerKey() + + +let test_zip () = + test "zip" + (Array.zip [|1..10|] [|1..10|] = [|for i in 1..10 -> i, i|]) + + let unzip1, unzip2 = Array.unzip <| [|for i in 1..10 -> i, i+1|] + test "unzip" (unzip1 = [|1..10|] && unzip2 = [|2..11|]) + +let test_zip3 () = + test "zip3" + (Array.zip3 [|1..10|] [|1..10|] [|1..10|] = [|for i in 1..10 -> i, i, i|]) + + let unzip1, unzip2, unzip3 = Array.unzip3 <| [|for i in 1..10 -> i, i+1, i+2|] + test "unzip3" (unzip1 = [|1..10|] && unzip2 = [|2..11|] && unzip3 = [|3..12|]) + + +let test_rev () = + test "rev a" + (Array.rev [|0..100|] = [|100..-1 ..0|]) + + test "rev b" + (Array.rev [|1|] = [|1|]) + + test "rev c" + (Array.rev [||] = [||]) + + test "rev d" + (Array.rev [|1; 2|] = [|2; 1|]) + +let test_sum () = + test "sum a" (Array.sum [||] = 0) + test "sum b" (Array.sum [|42|] = 42) + test "sum c" (Array.sum [|42;-21|] = 21) + test "sum d" (Array.sum [|1..1000|] = (1000*1001) / 2) + test "sum e" (Array.sum [|1.;2.;3.|] = 6.) + test "sum f" (Array.sum [|1.;2.;infinity;3.|] = infinity) + +let test_sum_by () = + test "sum_by a" (Array.sumBy int [||] = 0) + test "sum_by b" (Array.sumBy int [|42|] = 42) + test "sum_by c" (Array.sumBy int [|42;-21|] = 21) + test "sum_by d" (Array.sumBy int [|1..1000|] = (1000*1001) / 2) + test "sum_by e" (Array.sumBy float [|1.;2.;3.|] = 6.) + test "sum_by f" (Array.sumBy float [|1.;2.;infinity;3.|] = infinity) + test "sum_by g" (Array.sumBy abs [|1; -2; 3; -4|] = 10) + test "sum_by h" (Array.sumBy String.length [|"abcd";"efg";"hi";"j";""|] = 10) + +let test_average () = + test "average a1" (try Array.average ([||]: float array) |> ignore; false with :? System.ArgumentException -> true) + test "average a2" (try Array.average ([||]: float32 array) |> ignore; false with :? System.ArgumentException -> true) + test "average a3" (try Array.average ([||]: decimal array) |> ignore; false with :? System.ArgumentException -> true) + test "average a4" (Array.average [|0.|] = 0.) + test "average b" (Array.average [|4.|] = 4.) + test "average c" (Array.average [|4.;6.|] = 5.) + + test "average_by a1" (try Array.averageBy id ([||]: float array) |> ignore; false with :? System.ArgumentException -> true) + test "average_by a2" (try Array.averageBy id ([||]: float32 array) |> ignore; false with :? System.ArgumentException -> true) + test "average_by a3" (try Array.averageBy id ([||]: decimal array) |> ignore; false with :? System.ArgumentException -> true) + test "average_by a4" (Array.averageBy float [|0..1000|] = 500.) + test "average_by b" (Array.averageBy (String.length >> float) [|"ab";"cdef"|] = 3.) + +let test_min () = + test "min a" (Array.min [|42|] = 42) + test "min b" (Array.min [|42;21|] = 21) + test "min c" (Array.min [|'a';'b'|] = 'a') + + test "max a" (Array.max [|42|] = 42) + test "max b" (Array.max [|42;21|] = 42) + test "max c" (Array.max [|'a';'b'|] = 'b') + +let test_min_by () = + test "min_by a" (Array.minBy int [|42|] = 42) + test "min_by b" (Array.minBy abs [|-42;-21|] = -21) + test "min_by c" (Array.minBy int [|'a';'b'|] = 'a') + + test "max_by a" (Array.maxBy int [|42|] = 42) + test "max_by b" (Array.maxBy abs [|-42;-21|] = -42) + test "max_by c" (Array.maxBy int [|'a';'b'|] = 'b') + +let test_seq () = + test "to_seq" (Array.ofSeq [1..100] = [|1..100|]) + test "to_seq" ([|1..100|] |> Array.toSeq |> Array.ofSeq = [|1..100|]) + + +let test_zero_create () = + let arr = Array.zeroCreate 3 in + ignore (Array.set arr 0 4); + ignore (Array.set arr 1 3); + ignore (Array.set arr 2 2); + test "fewoih" (Array.get arr 0 = 4); + test "vvrew0" (Array.get arr 1 = 3); + test "vvrew0" (Array.get arr 2 = 2) + +let test_zero_create_2 () = + let arr = Array.zeroCreate 0 in + test "sdio2" (Array.length arr = 0) + +let test_init () = + let arr = Array.init 4 (fun x -> x + 1) in + test "test2927: sdvjk2" (Array.get arr 0 = 1); + test "test2927: cedkj" (Array.get arr 2 = 3) + +let test_init_empty () = + let arr = Array.init 0 (fun x -> x + 1) in + test "test2927: sdvjk2" (Array.length arr = 0) + +let test_append () = + let arr = Array.append ( [| "4";"3" |]) ( [| "2" |]) in + test "test2928: sdvjk2" (Array.get arr 0 = "4"); + test "test2928: cedkj" (Array.get arr 2 = "2"); + test "test2928: cedkj" (Array.length arr = 3) + +let test_append_empty () = + let arr = Array.append ( [| |]) ( [| |]) in + test "test2928: cedkj" (Array.length arr = 0) + +let test_fill () = + let arr = [| "4";"3";"2" |] in + Array.fill arr 1 2 "1"; + test "test2929: sdvjk2" (Array.get arr 0 = "4"); + test "test2929: cedkj" (Array.get arr 2 = "1") + +let test_copy () = + let arr = [| "4";"3";"2" |] in + let arr2 = Array.copy arr in + test "test2929: sdvjk2" (Array.get arr2 0 = "4"); + test "test2929: cedkj" (Array.get arr2 2 = "2"); + test "feio" (not (LanguagePrimitives.PhysicalEquality arr arr2)) + +let test_blit () = + let arr = [| "4";"3";"2";"0" |] in + let arr2 = [| "4";"3";"-1"; "-1" |] in + Array.blit arr 1 arr2 2 2; + test "test2930: sdvjk2" (Array.get arr2 0 = "4"); + test "test2930: cedkj" (Array.get arr2 1 = "3"); + test "test2930: ceddwkj" (Array.get arr2 2 = "3"); + test "test2930: ceqwddkj" (Array.get arr2 3 = "2") + +let test_of_list () = + let arr = Array.ofList [ "4";"3";"2";"0" ] in + test "test2931: sdvjk2" (Array.get arr 0 = "4"); + test "test2931: cedkj" (Array.get arr 1 = "3"); + test "test2931: ceddwkj" (Array.get arr 2 = "2"); + test "test2931: ceqwddkj" (Array.get arr 3 = "0") + +let test_to_list () = + test "test2932" (Array.toList ( [| "4";"3";"2";"0" |]) = [ "4";"3";"2";"0" ]) + +let test_to_list_of_list () = + test "test2933" (Array.toList (Array.ofList [ "4";"3";"2";"0" ]) = [ "4";"3";"2";"0" ]) + +let test_fold_left () = + let arr = Array.ofList [ 4;3;2;1 ] in + test "test2931: sdvjk2few" (Array.fold (fun x y -> x/y) (5*4*3*2*1) arr = 5) + +let test_fold_right () = + let arr = Array.ofList [ 4;3;2;1 ] in + test "test2931: sdvjk2ew" (Array.foldBack (fun y x -> x/y) arr (6*4*3*2*1) = 6) + +let test_reduce_left () = + test "test2931: array.reduce" (Array.reduce (fun x y -> x/y) [|5*4*3*2; 4;3;2;1|] = 5) + +let test_reduce_right () = + let arr = Array.ofList [ 4;3;2;1;5 ] in + test "test2931: array.reduceBack" (Array.reduceBack (fun y x -> x/y) [|4;3;2;1; 5*4*3*2|] = 5) + + +let _ = test_make_get_set_length () +let _ = test_const () +let _ = test_const_empty () +let _ = test_map () +let _ = test_mapi () +let _ = test_iter () +let _ = test_iteri () +let _ = test_mapi () +let _ = test_isEmpty () +let _ = test_create () +let _ = test_concat () +let _ = test_sub () +let _ = test_fold2 () +let _ = test_foldBack2 () +let _ = test_scan () +let _ = test_iter2 () +let _ = test_iteri2 () +let _ = test_iter () +let _ = test_map2 () +let _ = test_mapi2 () +let _ = test_exists () +let _ = test_forall () +let _ = test_iter () +let _ = test_exists2 () +let _ = test_forall2 () +let _ = test_filter () +let _ = test_partition () +let _ = test_choose () +let _ = test_find () +let _ = test_findIndex () +let _ = test_tryfind () +let _ = test_first () +let _ = test_sort () +let _ = test_sort_by () +let _ = test_zip () +let _ = test_zip3 () +let _ = test_rev () +let _ = test_sum () +let _ = test_sum_by () +let _ = test_average () +let _ = test_min () +let _ = test_min_by () +let _ = test_seq () +let _ = test_zero_create () +let _ = test_zero_create_2 () +let _ = test_append () +let _ = test_append_empty () +let _ = test_init () +let _ = test_init_empty () +let _ = test_fill () +let _ = test_blit () +let _ = test_of_list () +let _ = test_to_list () +let _ = test_to_list_of_list () +let _ = test_copy () +let _ = test_iter () +let _ = test_iteri () +let _ = test_fold_left () +let _ = test_fold_right () +let _ = test_reduce_left () +let _ = test_reduce_right () + +module Array2Tests = begin + + let test_make_get_set_length () = + let arr = Array2D.create 3 4 0 in + test "fewoih1" (Array2D.get arr 0 0 = 0); + test "fewoih2" (Array2D.get arr 0 1 = 0); + test "vvrew03" (Array2D.get arr 2 2 = 0); + test "vvrew04" (Array2D.get arr 2 3 = 0); + ignore (Array2D.set arr 0 2 4); + test "vsdiuvs5" (Array2D.get arr 0 2 = 4); + arr.[0,2] <- 2; + test "vsdiuvs6" (arr.[0,2] = 2); + test "vropivrwe7" (Array2D.length1 arr = 3); + test "vropivrwe8" (Array2D.length2 arr = 4) + + let a = Array2D.init 10 10 (fun i j -> i,j) + let b = Array2D.init 2 2 (fun i j -> i+1,j+1) + //test "a2_sub" + // (Array2D.sub a 1 1 2 2 = b) + + + Array2D.blit b 0 0 a 0 0 2 2 + //test "a2_blit" + // (Array2D.sub a 0 0 2 2 = b) + + let _ = test_make_get_set_length () + + +end + +module ArrayNonZeroBasedTestsSlice = + let runTest () = + let arr = (Array2D.initBased 5 4 3 2 (fun i j -> (i,j))) + test "fewoih1" (arr.[6,*] = [|(6, 4); (6, 5)|]) + test "fewoih2" (arr.[*,*].[1,*] = [|(6, 4); (6, 5)|]) + test "fewoih3" (arr.[*,5] = [|(5, 5); (6, 5); (7, 5)|]) + test "fewoih4" (arr.[*,*].[*,1] = [|(5, 5); (6, 5); (7, 5)|]) + test "fewoih5" (arr.GetLowerBound(0) = 5) + test "fewoih6" (arr.GetLowerBound(1) = 4) + test "fewoih7" (arr.[*,*].GetLowerBound(0) = 0) + test "fewoih8" (arr.[*,*].GetLowerBound(1) = 0) + test "fewoih9" (arr.[*,*].[0..,1] = [|(5, 5); (6, 5); (7, 5)|]) + test "fewoih10" (arr.[*,*].[1..,1] = [|(6, 5); (7, 5)|]) + let arr2d = + let arr = Array2D.zeroCreateBased 5 4 3 2 + for i in 5..7 do for j in 4..5 do arr.[i,j] <- (i,j) + arr + let arr2d2 = + let arr = Array2D.zeroCreate 3 2 + for i in 0..2 do for j in 0..1 do arr.[i,j] <- (j,i) + arr + test "fewoih11" (arr2d.[6..6,5] = [|(6, 5)|]) + test "fewoih11" (arr2d.[..6,5] = [|(5, 5); (6, 5)|]) + test "fewoih11" (arr2d.[6..,5] = [|(6, 5); (7, 5)|]) + test "fewoih12" (arr2d.[*,*].[1..,1] = [|(6, 5); (7, 5)|]) + arr2d.[*,*] <- arr2d2 + test "fewoih13" (arr2d.[*,*].[0..0,1] = [|(1, 0)|]) + test "fewoih13" (arr2d.[*,*].[1..,1] = [|(1, 1); (1, 2)|]) + test "fewoih13" (arr2d.[*,*].[1,1..] = [|(1, 1)|]) + test "fewoih13" (arr2d.[*,*].[1,0..0] = [|(0, 1)|]) + let arr3d = + let arr = System.Array.CreateInstance(typeof, [| 3;2;1 |], [|5;4;3|]) :?> (int*int*int)[,,] + for i in 5..7 do for j in 4..5 do for k in 3..3 do arr.[i,j,k] <- (i,j,k) + arr + let arr3d2 = + let arr = System.Array.CreateInstance(typeof, [| 3;2;1 |]) :?> (int*int*int)[,,] + for i in 0..2 do for j in 0..1 do for k in 0..0 do arr.[i,j,k] <- (k,j,i) + arr + + test "fewoih14" (arr3d.[5,4,3] = (5,4,3)) + test "fewoih15" (arr3d.[*,*,*].[0,0,0] = (5,4,3)) + arr3d.[*,*,*] <- arr3d2 + test "fewoih16" (arr3d.[5,4,3] = (0,0,0)) + test "fewoih16" (arr3d.[5,5,3] = (0,1,0)) + test "fewoih16" (arr3d.[6,5,3] = (0,1,1)) + let _ = runTest() + +module Array3Tests = begin + + let test_make_get_set_length () = + let arr = Array3D.create 3 4 5 0 in + test "fewoih1" (Array3D.get arr 0 0 0 = 0); + test "fewoih2" (Array3D.get arr 0 1 0 = 0); + test "vvrew03" (Array3D.get arr 2 2 2 = 0); + test "vvrew04" (Array3D.get arr 2 3 4 = 0); + ignore (Array3D.set arr 0 2 3 4); + test "vsdiuvs5" (Array3D.get arr 0 2 3 = 4); + arr.[0,2,3] <- 2; + test "vsdiuvs6" (arr.[0,2,3] = 2); + arr.[0,2,3] <- 3; + test "vsdiuvs" (arr.[0,2,3] = 3); + test "vropivrwe7" (Array3D.length1 arr = 3); + test "vropivrwe8" (Array3D.length2 arr = 4); + test "vropivrwe9" (Array3D.length3 arr = 5) + + let _ = test_make_get_set_length () + +end + +module Array4Tests = begin + + let test_make_get_set_length () = + let arr = Array4D.create 3 4 5 6 0 in + arr.[0,2,3,4] <- 2; + test "vsdiuvsq" (arr.[0,2,3,4] = 2); + arr.[0,2,3,4] <- 3; + test "vsdiuvsw" (arr.[0,2,3,4] = 3); + test "vsdiuvsw" (Array4D.get arr 0 2 3 4 = 3); + Array4D.set arr 0 2 3 4 5; + test "vsdiuvsw" (Array4D.get arr 0 2 3 4 = 5); + test "vropivrwee" (Array4D.length1 arr = 3); + test "vropivrwer" (Array4D.length2 arr = 4); + test "vropivrwet" (Array4D.length3 arr = 5) + test "vropivrwey" (Array4D.length4 arr = 6) + + let test_init () = + let arr = Array4D.init 3 4 5 6 (fun i j k m -> i+j+k+m) in + test "vsdiuvs1" (arr.[0,2,3,4] = 9); + test "vsdiuvs2" (arr.[0,2,3,3] = 8); + test "vsdiuvs3" (arr.[0,0,0,0] = 0); + arr.[0,2,3,4] <- 2; + test "vsdiuvs4" (arr.[0,2,3,4] = 2); + arr.[0,2,3,4] <- 3; + test "vsdiuvs5" (arr.[0,2,3,4] = 3); + test "vropivrwe1" (Array4D.length1 arr = 3); + test "vropivrwe2" (Array4D.length2 arr = 4); + test "vropivrwe3" (Array4D.length3 arr = 5) + test "vropivrwe4" (Array4D.length4 arr = 6) + + let _ = test_make_get_set_length () + let _ = test_init () + +end + +module Array2TestsNoDot = begin + + let test_make_get_set_length () = + let arr = Array2D.create 3 4 0 in + test "fewoih1" (Array2D.get arr 0 0 = 0); + test "fewoih2" (Array2D.get arr 0 1 = 0); + test "vvrew03" (Array2D.get arr 2 2 = 0); + test "vvrew04" (Array2D.get arr 2 3 = 0); + ignore (Array2D.set arr 0 2 4); + test "vsdiuvs5" (Array2D.get arr 0 2 = 4); + arr[0,2] <- 2; + test "vsdiuvs6" (arr[0,2] = 2); + test "vropivrwe7" (Array2D.length1 arr = 3); + test "vropivrwe8" (Array2D.length2 arr = 4) + + let a = Array2D.init 10 10 (fun i j -> i,j) + let b = Array2D.init 2 2 (fun i j -> i+1,j+1) + //test "a2_sub" + // (Array2D.sub a 1 1 2 2 = b) + + + Array2D.blit b 0 0 a 0 0 2 2 + //test "a2_blit" + // (Array2D.sub a 0 0 2 2 = b) + + let _ = test_make_get_set_length () + + +end + +module ArrayNonZeroBasedTestsSliceNoDot = + let runTest () = + let arr = (Array2D.initBased 5 4 3 2 (fun i j -> (i,j))) + test "fewoih1" (arr[6,*] = [|(6, 4); (6, 5)|]) + test "fewoih2" (arr[*,*][1,*] = [|(6, 4); (6, 5)|]) + test "fewoih3" (arr[*,5] = [|(5, 5); (6, 5); (7, 5)|]) + test "fewoih4" (arr[*,*][*,1] = [|(5, 5); (6, 5); (7, 5)|]) + test "fewoih5" (arr.GetLowerBound(0) = 5) + test "fewoih6" (arr.GetLowerBound(1) = 4) + test "fewoih7" (arr[*,*].GetLowerBound(0) = 0) + test "fewoih8" (arr[*,*].GetLowerBound(1) = 0) + test "fewoih9" (arr[*,*][0..,1] = [|(5, 5); (6, 5); (7, 5)|]) + test "fewoih10" (arr[*,*][1..,1] = [|(6, 5); (7, 5)|]) + let arr2d = + let arr = Array2D.zeroCreateBased 5 4 3 2 + for i in 5..7 do for j in 4..5 do arr[i,j] <- (i,j) + arr + let arr2d2 = + let arr = Array2D.zeroCreate 3 2 + for i in 0..2 do for j in 0..1 do arr[i,j] <- (j,i) + arr + test "fewoih11" (arr2d[6..6,5] = [|(6, 5)|]) + test "fewoih11" (arr2d[..6,5] = [|(5, 5); (6, 5)|]) + test "fewoih11" (arr2d[6..,5] = [|(6, 5); (7, 5)|]) + test "fewoih12" (arr2d[*,*][1..,1] = [|(6, 5); (7, 5)|]) + arr2d[*,*] <- arr2d2 + test "fewoih13" (arr2d[*,*][0..0,1] = [|(1, 0)|]) + test "fewoih13" (arr2d[*,*][1..,1] = [|(1, 1); (1, 2)|]) + test "fewoih13" (arr2d[*,*][1,1..] = [|(1, 1)|]) + test "fewoih13" (arr2d[*,*][1,0..0] = [|(0, 1)|]) + let arr3d = + let arr = System.Array.CreateInstance(typeof, [| 3;2;1 |], [|5;4;3|]) :?> (int*int*int)[,,] + for i in 5..7 do for j in 4..5 do for k in 3..3 do arr[i,j,k] <- (i,j,k) + arr + let arr3d2 = + let arr = System.Array.CreateInstance(typeof, [| 3;2;1 |]) :?> (int*int*int)[,,] + for i in 0..2 do for j in 0..1 do for k in 0..0 do arr[i,j,k] <- (k,j,i) + arr + + test "fewoih14" (arr3d[5,4,3] = (5,4,3)) + test "fewoih15" (arr3d[*,*,*][0,0,0] = (5,4,3)) + arr3d[*,*,*] <- arr3d2 + test "fewoih16" (arr3d[5,4,3] = (0,0,0)) + test "fewoih16" (arr3d[5,5,3] = (0,1,0)) + test "fewoih16" (arr3d[6,5,3] = (0,1,1)) + let _ = runTest() + +module Array3TestsNoDot = begin + + let test_make_get_set_length () = + let arr = Array3D.create 3 4 5 0 in + test "fewoih1" (Array3D.get arr 0 0 0 = 0); + test "fewoih2" (Array3D.get arr 0 1 0 = 0); + test "vvrew03" (Array3D.get arr 2 2 2 = 0); + test "vvrew04" (Array3D.get arr 2 3 4 = 0); + ignore (Array3D.set arr 0 2 3 4); + test "vsdiuvs5" (Array3D.get arr 0 2 3 = 4); + arr[0,2,3] <- 2; + test "vsdiuvs6" (arr[0,2,3] = 2); + arr[0,2,3] <- 3; + test "vsdiuvs" (arr[0,2,3] = 3); + test "vropivrwe7" (Array3D.length1 arr = 3); + test "vropivrwe8" (Array3D.length2 arr = 4); + test "vropivrwe9" (Array3D.length3 arr = 5) + + let _ = test_make_get_set_length () + +end + +module Array4TestsNoDot = begin + + let test_make_get_set_length () = + let arr = Array4D.create 3 4 5 6 0 in + arr[0,2,3,4] <- 2; + test "vsdiuvsq" (arr[0,2,3,4] = 2); + arr[0,2,3,4] <- 3; + test "vsdiuvsw" (arr[0,2,3,4] = 3); + test "vsdiuvsw" (Array4D.get arr 0 2 3 4 = 3); + Array4D.set arr 0 2 3 4 5; + test "vsdiuvsw" (Array4D.get arr 0 2 3 4 = 5); + test "vropivrwee" (Array4D.length1 arr = 3); + test "vropivrwer" (Array4D.length2 arr = 4); + test "vropivrwet" (Array4D.length3 arr = 5) + test "vropivrwey" (Array4D.length4 arr = 6) + + let test_init () = + let arr = Array4D.init 3 4 5 6 (fun i j k m -> i+j+k+m) in + test "vsdiuvs1" (arr[0,2,3,4] = 9); + test "vsdiuvs2" (arr[0,2,3,3] = 8); + test "vsdiuvs3" (arr[0,0,0,0] = 0); + arr[0,2,3,4] <- 2; + test "vsdiuvs4" (arr[0,2,3,4] = 2); + arr[0,2,3,4] <- 3; + test "vsdiuvs5" (arr[0,2,3,4] = 3); + test "vropivrwe1" (Array4D.length1 arr = 3); + test "vropivrwe2" (Array4D.length2 arr = 4); + test "vropivrwe3" (Array4D.length3 arr = 5) + test "vropivrwe4" (Array4D.length4 arr = 6) + + let _ = test_make_get_set_length () + let _ = test_init () + +end + +#if PERF +let test_map_perf () = + let arr1 = [| 4;3;2 |] in + let res = ref (Array.map (fun x -> x + 1) arr1) in + for i = 1 to 20000000 do + res := Array.map (fun x -> x + 1) arr1 + done; + test "test2927: sdvjk2" (Array.get !res 0 = 5) + +let _ = test_map_perf() +#endif + +module SeqCacheAllTest = + let s2 = + let count = ref 0 + let s = Seq.cache (seq { for i in 0 .. 10 -> (incr count; i) }) :> seq<_> + let test0 = (!count = 0) + let e1 = s.GetEnumerator() + let test1 = (!count = 0) + printf "test1 = %b\n" test1; + for i = 1 to 1 do (e1.MoveNext() |> ignore; e1.Current |> ignore) + let test2 = (!count = 1) + printf "test2 = %b\n" test2; + let e2 = s.GetEnumerator() + for i = 1 to 5 do (e2.MoveNext() |> ignore; e2.Current |> ignore) + let test3 = (!count = 5) + printf "test3 = %b\n" test3; + let e3 = s.GetEnumerator() + for i = 1 to 5 do (e3.MoveNext() |> ignore; e3.Current |> ignore) + let test4 = (!count = 5) + printf "test4 = %b\n" test4; + let e4 = s.GetEnumerator() + for i = 1 to 3 do (e4.MoveNext() |> ignore; e4.Current |> ignore) + let test5 = (!count = 5) + printf "test5 = %b\n" test5; + + let test6 = [ for x in s -> x ] = [ 0 .. 10 ] + printf "test6 = %b\n" test6; + for x in s do () + let test7 = (!count = 11) + let test8 = [ for x in s -> x ] = [ 0 .. 10 ] + let test9 = !count = 11 + test "test0" test0 + test "test1" test1 + test "test2" test2 + test "test3" test3 + test "test4" test4 + test "test5" test5 + test "test6" test6 + test "test7" test7 + test "test8" test8 + test "test9" test9 + +module MiscIndexNotationTests = + [] + type foo + let m, n = 1, 10 + let vs1 = seq { 1 .. 2 .. 3 } + let vs2 = [ 1 .. 2 .. 4 ] + let vs3 = [m .. 1 .. n] + let vs4 = [| 1 .. 2 .. 4 |] + let vs5 = [| m .. 1 .. n |] + + let arr = [| 1;2;3;4;5 |] + let arr2 : int[,] = Array2D.zeroCreate 5 5 + + let v1 = arr[1] + let v2 = arr2[1,1] + let v3 = arr[1..3] + + let v4 = arr[..3] + let v5 = arr[1..] + let v6 = arr[*] + + let v7 = arr2[1..3,1..3] + let v8 = arr2[..3,1..3] + let v9 = arr2[1..,1..3] + let v10 = arr2[*,1..3] + let v11 = arr2[1..3,1..] + let v12 = arr2[..3,1..] + let v13 = arr2[1..,1..] + let v14 = arr2[*,1..] + let v15 = arr2[1..3,..3] + let v16 = arr2[..3,..3] + let v17 = arr2[1..,..3] + let v18 = arr2[*,..3] + let v19 = arr2[1..3,*] + let v20 = arr2[..3,*] + let v21 = arr2[1..,*] + let v22 = arr2[*,*] + + module Apps = + let arrf () = arr + let arrf2 () = arr2 + let v1 = arrf()[1] + let v2 = arrf2()[1,1] + let v3 = arrf()[1..3] + + let v4 = arrf()[..3] + let v5 = arrf()[1..] + let v6 = arrf()[*] + + let v7 = arrf2()[1..3,1..3] + let v8 = arrf2()[..3,1..3] + let v9 = arrf2()[1..,1..3] + let v10 = arrf2()[*,1..3] + let v11 = arrf2()[1..3,1..] + let v12 = arrf2()[..3,1..] + let v13 = arrf2()[1..,1..] + let v14 = arrf2()[*,1..] + let v15 = arrf2()[1..3,..3] + let v16 = arrf2()[..3,..3] + let v17 = arrf2()[1..,..3] + let v18 = arrf2()[*,..3] + let v19 = arrf2()[1..3,*] + let v20 = arrf2()[..3,*] + let v21 = arrf2()[1..,*] + let v22 = arrf2()[*,*] + +module ArrayStructMutation = + module Array1D = + module Test1 = + [] + type T = + val mutable i : int + let a = Array.create 10 Unchecked.defaultof + a.[0].i <- 27 + check "wekvw0301" 27 a.[0].i + + + module Test2 = + + [] + type T = + val mutable public i : int + member public this.Set i = this.i <- i + let a = Array.create 10 Unchecked.defaultof + a.[0].Set 27 + a.[2].Set 27 + check "wekvw0302" 27 a.[0].i + check "wekvw0303" 27 a.[2].i + + module Array2D = + module Test1 = + [] + type T = + val mutable i : int + let a = Array2D.create 10 10 Unchecked.defaultof + a.[0,0].i <- 27 + check "wekvw0304" 27 a.[0,0].i + + + module Test2 = + + [] + type T = + val mutable public i : int + member public this.Set i = this.i <- i + let a = Array2D.create 10 10 Unchecked.defaultof + a.[0,0].Set 27 + a.[0,2].Set 27 + check "wekvw0305" 27 a.[0,0].i + check "wekvw0306" 27 a.[0,2].i + + + module Array3D = + module Test1 = + [] + type T = + val mutable i : int + let a = Array3D.create 10 10 10 Unchecked.defaultof + a.[0,0,0].i <- 27 + a.[0,2,3].i <- 27 + check "wekvw0307" 27 a.[0,0,0].i + check "wekvw0308" 27 a.[0,2,3].i + + + module Test2 = + + [] + type T = + val mutable public i : int + member public this.Set i = this.i <- i + let a = Array3D.create 10 10 10 Unchecked.defaultof + a.[0,0,0].Set 27 + a.[0,2,3].Set 27 + check "wekvw0309" 27 a.[0,0,0].i + check "wekvw030q" 27 a.[0,2,3].i + + module Array4D = + module Test1 = + [] + type T = + val mutable i : int + let a = Array4D.create 10 10 10 10 Unchecked.defaultof + a.[0,0,0,0].i <- 27 + a.[0,2,3,4].i <- 27 + check "wekvw030w" 27 a.[0,0,0,0].i + check "wekvw030e" 27 a.[0,2,3,4].i + + + module Test2 = + + [] + type T = + val mutable public i : int + member public this.Set i = this.i <- i + let a = Array4D.create 10 10 10 10 Unchecked.defaultof + a.[0,0,0,0].Set 27 + a.[0,2,3,4].Set 27 + check "wekvw030r" 27 a.[0,0,0,0].i + check "wekvw030t" 27 a.[0,2,3,4].i + +module LoopTests = + let loop3 a N = + let mutable x = 0 in + // In this loop, the types of 'a' and 'N' are not known prior to the loop + for i in (min a a) .. N do + x <- x + 1 + done; + check (sprintf "clkrerev90-%A" (a,N)) x (if N < a then 0 else N - a + 1) + + + do loop3 0 10 + do loop3 0 0 + do loop3 0 -1 + do loop3 10 9 + + let loop4 a N = + let mutable x = 0 in + for i in OperatorIntrinsics.RangeInt32 a 1 N do + x <- x + 1 + done; + check (sprintf "clkrerev91-%A" (a,N)) x (if N < a then 0 else N - a + 1) + + do loop4 0 10 + do loop4 0 0 + do loop4 0 -1 + do loop4 10 9 + + let loop5 a N = + let mutable x = 0 in + // In this loop, the types of 'a' and 'N' are not known prior to the loop + for i in (min a a) .. 2 .. (min N N) do + x <- x + 1 + done; + check (sprintf "clkrerev92-%A" (a,N)) x ((if N < a then 0 else N - a + 2) / 2) + + do loop5 0 10 + do loop5 0 0 + do loop5 0 -1 + do loop5 10 9 + + + let loop6 a N = + let mutable x = 0 in + // In this loop, the types of 'a' and 'N' are not known prior to the loop + for i in (min a a) .. 200 .. (min N N) do + x <- x + 1 + done; + check (sprintf "clkrerev93-%A" (a,N)) x ((if N < a then 0 else N - a + 200) / 200) + + do loop6 0 10 + do loop6 0 0 + do loop6 0 -1 + do loop6 10 9 + + + let loop7 a step N = + let mutable x = 0 in + // In this loop, the types of 'a' and 'N' are not known prior to the loop + for i in (min a a) .. step .. (min N N) do + x <- x + 1 + done; + check (sprintf "clkrerev95-%A" (a,step,N)) x (if step < 0 then (if a < N then 0 else (a - N + abs step) / abs step) else (if N < a then 0 else N - a + step) / step) + + do loop7 0 1 10 + do loop7 0 -1 0 + do loop7 0 2 -1 + do loop7 10 -2 9 + + let loop8 a N = + let mutable x = 0 in + // In this loop, the types of 'a' and 'N' are not known prior to the loop + for i in (min a a) .. -1 .. (min N N) do + x <- x + 1 + done; + check (sprintf "clkrerev96-%A" (a,N)) x (abs (if a < N then 0 else (a - N + 1) / 1)) + + do loop8 0 10 + do loop8 0 0 + do loop8 0 -1 + do loop8 10 9 + +// Some more adhoc testing - the use of 'min' gives rise to a let binding in optimized code +module MoreLoopTestsWithLetBindings = + let loop3 a N = + let mutable x = 0 in + // In this loop, the types of 'a' and 'N' are not known prior to the loop + for i in (min a a) .. (min N N) do + x <- x + 1 + done; + check (sprintf "ffclkrerev90-%A" (a,N)) x (if N < a then 0 else N - a + 1) + + + do loop3 0 10 + do loop3 0 0 + do loop3 0 -1 + do loop3 10 9 + do for start in -3 .. 3 do for finish in -3 .. 3 do loop3 start finish + + let loop4 a N = + let mutable x = 0 in + for i in OperatorIntrinsics.RangeInt32 a 1 N do + x <- x + 1 + done; + check (sprintf "ffclkrerev91-%A" (a,N)) x (if N < a then 0 else N - a + 1) + + do loop4 0 10 + do loop4 0 0 + do loop4 0 -1 + do loop4 10 9 + do for start in -3 .. 3 do for finish in -3 .. 3 do loop4 start finish + + let loop5 a N = + let mutable x = 0 in + // In this loop, the types of 'a' and 'N' are not known prior to the loop + for i in (min a a) .. 2 .. (min N N) do + x <- x + 1 + done; + check (sprintf "ffclkrerev92-%A" (a,N)) x ((if N < a then 0 else N - a + 2) / 2) + + do loop5 0 10 + do loop5 0 0 + do loop5 0 -1 + do loop5 10 9 + do for start in -3 .. 3 do for finish in -3 .. 3 do loop5 start finish + + + let loop6 a N = + let mutable x = 0 in + // In this loop, the types of 'a' and 'N' are not known prior to the loop + for i in (min a a) .. 200 .. (min N N) do + x <- x + 1 + done; + check (sprintf "ffclkrerev93-%A" (a,N)) x ((if N < a then 0 else N - a + 200) / 200) + + do loop6 0 10 + do loop6 0 0 + do loop6 0 -1 + do loop6 10 9 + do for start in -3 .. 3 do for finish in -3 .. 3 do loop6 start finish + + + let loop7 a step N = + let mutable x = 0 in + // In this loop, the types of 'a' and 'N' are not known prior to the loop + for i in (min a a) .. step .. (min N N) do + x <- x + 1 + done; + check (sprintf "ffclkrerev95-%A" (a,step,N)) x (if step < 0 then (if a < N then 0 else (a - N + abs step) / abs step) else (if N < a then 0 else N - a + step) / step) + + do loop7 0 1 10 + do loop7 0 -1 0 + do loop7 0 2 -1 + do loop7 10 -2 9 + do for start in -3 .. 3 do for finish in -3 .. 3 do for step in [-2; -1; 1; 2] do loop7 start step finish + + let loop8 a N = + let mutable x = 0 in + // In this loop, the types of 'a' and 'N' are not known prior to the loop + for i in (min a a) .. -1 .. (min N N) do + x <- x + 1 + done; + check (sprintf "ffclkrerev96-%A" (a,N)) x (abs (if a < N then 0 else (a - N + 1) / 1)) + + do loop8 0 10 + do loop8 0 0 + do loop8 0 -1 + do loop8 10 9 + do for start in -3 .. 3 do for finish in -3 .. 3 do loop8 start finish + +module bug872632 = + type MarkerStyle = + | None = 0 + | Square = 1 + | Circle = 2 + | Diamond = 3 + | Triangle = 4 + | Triangle1 = 10 + | Cross = 5 + | Star4 = 6 + | Star5 = 7 + | Star6 = 8 + | Star10 = 9 + + + + module Foo = + let x = [| + MarkerStyle.Circle + MarkerStyle.Cross + MarkerStyle.Star6 + MarkerStyle.Diamond + MarkerStyle.Square + MarkerStyle.Star10 + MarkerStyle.Triangle + MarkerStyle.Triangle1 + |] + + do check "bug872632" Foo.x.Length 8 + +module CheckUnionTypesAreSealed = + open System +#if NETCOREAPP + open System.Reflection + type System.Type with + member this.IsSealed + with get () = this.GetTypeInfo().IsSealed +#endif + + do check "vwllfewlkefw1" (typedefof>.IsSealed) true + do check "vwllfewlkefw2" (typedefof>.IsSealed) true + type X1 = A | B + do check "vwllfewlkefw3" (typedefof.IsSealed) true + type X2 = A | B of string + do check "vwllfewlkefw4" (typedefof.IsSealed) false + type X3 = A | B | C + do check "vwllfewlkefw5" (typedefof.IsSealed) true + type X4 = A | B | C | D | E | F | G | H | I + do check "vwllfewlkefw5" (typedefof.IsSealed) true + + [] + type SetTree<'T> = + | SetEmpty + | SetNode of 'T * SetTree<'T> * SetTree<'T> + do check "vwllfewlkefw6" (typedefof>.IsSealed) true + + type SetTree2<'T> = + | SetEmpty + | SetNode of 'T * SetTree2<'T> * SetTree2<'T> + do check "vwllfewlkefw6" (typedefof>.IsSealed) false + +module manyIndexes = + open System + + // Bug in F# 3.1: Indexer Properties was incorrectly limited to 4 arguments. There were no limits in previous versions of F#, and shouldn't be in future versions + // Repro code for bug in F# 3.1. This compiles perfectly in F# 3.0 + + // ---------------------------------------------------------------------------- + type Test () = + /// Variable number of arguments with indexer property + member x.Item with get ([] objs: obj[]) = objs + + /// PASS: Variable number of arguments with member function + member x.Foo ([] objs: obj[]) = objs + + // ---------------------------------------------------------------------------- + let CompileIndexerTest = + let test = Test () + + // No problems with method having vaiable number of parameters + let u1 = test.Foo(null, null, null, null) + let u2 = test.Foo(null, null, null, null, null) + let u3 = test.Foo(null, null, null, null, null, null, null, null, null) + + // Bug was that the indexer Property was limited to 4 parameters (Issue introduced by matrix slicing code) + let u4 = test.[null] + let u5 = test.[null, null] + let u6 = test.[null, null, null] + let u7 = test.[null, null, null, null] + let u8 = test.[null, null, null, null, null] // Ensure that F# 3.1 is not unhappy with more than 4 arguments + let u9 = test.[null, null, null, null, null, null, null, null, null, null, null, null, null] // Ensure that F# 3.1 is not unhappy with many more than 4 arguments, 13 arguments would be really unlucky + 0 + + +#if !NETCOREAPP +module bug6447 = + let a = System.Array.CreateInstance(typeof, [|1|], [|1|]) + let a1 = System.Array.CreateInstance(typeof, [|1|], [|3|]) + let a2 = System.Array.CreateInstance(typeof, [|3|], [|1|]) + + do check "bug6447_bound1" a a + do check "bug6447_bound3" a1 a1 + do check "bug6447_bound1_3" a2 a2 + do check "bug6447_a_lt_a" (Unchecked.compare a a) 0 + do check "bug6447_a_eq_a1" (Unchecked.equals a a1) false + do check "bug6447_a_lt_a1" (Unchecked.compare a a1) -1 + do check "bug6447_a_lt_a1" (Unchecked.compare a1 a) 1 + do check "bug6447_a_eq_a2" (Unchecked.equals a a2) false + do check "bug6447_a_lt_a2" (Unchecked.compare a a2) -1 + do check "bug6447_a_lt_a2" (Unchecked.compare a2 a) 1 + do check "bug6447_a1_eq_a2" (Unchecked.equals a1 a2) false + do check "bug6447_a1_gt_a2" (Unchecked.compare a2 a1) 1 + do check "bug6447_a1_lt_a2" (Unchecked.compare a1 a2) -1 + do check "bug6447_a1_lt_a2" (Unchecked.compare a2 a1) 1 + do check "bug6447_a2_eq_a1" (Unchecked.equals a2 a1) false + do check "bug6447_a2_gt_a2" (Unchecked.compare a2 a1) 1 + do check "bug6447_a2_lt_a1" (Unchecked.compare a1 a2) -1 + do check "bug6447_hash_a" (hash a) 631 + do check "bug6447_hash_a1" (hash a1) 1893 + do check "bug6447_hash_a2" (hash a2) 10727 +#endif + +#if TESTS_AS_APP +let RUN() = failures +#else +let aa = + match failures with + | [] -> + stdout.WriteLine "Test Passed" + System.IO.File.WriteAllText("test.ok","ok") + exit 0 + | _ -> + stdout.WriteLine "Test Failed" + exit 1 +#endif +