Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/fsharp/CheckComputationExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1237,7 +1237,7 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol

// 'use! pat = e1 in e2' --> build.Bind(e1, (function _argN -> match _argN with pat -> build.Using(x, (fun _argN -> match _argN with pat -> e2))))
| SynExpr.LetOrUseBang (bindDebugPoint=spBind; isUse=true; isFromSource=isFromSource; pat=SynPat.Named (ident=id; isThisVal=false) as pat; rhs=rhsExpr; andBangs=[]; body=innerComp)
| SynExpr.LetOrUseBang (bindDebugPoint=spBind; isUse=true; isFromSource=isFromSource; pat=SynPat.LongIdent (longDotId=LongIdentWithDots(id=[id])) as pat; rhs=rhsExpr; andBangs=[]; body=innerComp) ->
| SynExpr.LetOrUseBang (bindDebugPoint=spBind; isUse=true; isFromSource=isFromSource; pat=SynPat.ParametersOwner (namePat = SingleIdentInParametersOwnerNamePat id) as pat; rhs=rhsExpr; andBangs=[]; body=innerComp) ->

let mBind = match spBind with DebugPointAtBinding.Yes m -> m | _ -> rhsExpr.Range
if isQuery then error(Error(FSComp.SR.tcBindMayNotBeUsedInQueries(), mBind))
Expand Down
7 changes: 4 additions & 3 deletions src/fsharp/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4831,7 +4831,7 @@ module TcDeclarations =
let attribs = attribs |> List.filter (fun a -> match a.Target with Some t when t.idText = "field" -> true | _ -> false)
let mLetPortion = synExpr.Range
let fldId = ident (CompilerGeneratedName id.idText, mLetPortion)
let headPat = SynPat.LongIdent (LongIdentWithDots([fldId], []), None, None, Some noInferredTypars, SynArgPats.Pats [], None, mLetPortion)
let headPat = SynPat.ParametersOwner (SynPat.Ident(fldId, fldId.idRange), None, None, Some noInferredTypars, SynArgPats.Pats [], None, mLetPortion)
let retInfo = match tyOpt with None -> None | Some ty -> Some (SynReturnInfo((ty, SynInfo.unnamedRetVal), ty.Range))
let isMutable =
match propKind with
Expand Down Expand Up @@ -4859,7 +4859,8 @@ module TcDeclarations =
let attribs = attribs |> List.filter (fun a -> match a.Target with Some t when t.idText = "field" -> false | _ -> true)
let fldId = ident (CompilerGeneratedName id.idText, mMemberPortion)
let headPatIds = if isStatic then [id] else [ident ("__", mMemberPortion);id]
let headPat = SynPat.LongIdent (LongIdentWithDots(headPatIds, []), None, None, Some noInferredTypars, SynArgPats.Pats [], None, mMemberPortion)
let headPatLid = LongIdentWithDots(headPatIds, [])
let headPat = SynPat.ParametersOwner (SynPat.LongIdent(headPatLid, headPatLid.Range), None, None, Some noInferredTypars, SynArgPats.Pats [], None, mMemberPortion)

match propKind, mGetSetOpt with
| SynMemberKind.PropertySet, Some m -> errorR(Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSetNotJustSet(), m))
Expand All @@ -4884,7 +4885,7 @@ module TcDeclarations =
| SynMemberKind.PropertyGetSet ->
let setter =
let vId = ident("v", mMemberPortion)
let headPat = SynPat.LongIdent (LongIdentWithDots(headPatIds, []), None, None, Some noInferredTypars, SynArgPats.Pats [mkSynPatVar None vId], None, mMemberPortion)
let headPat = SynPat.ParametersOwner (SynPat.LongIdent(headPatLid, headPatLid.Range), None, None, Some noInferredTypars, SynArgPats.Pats [mkSynPatVar None vId], None, mMemberPortion)
let rhsExpr = mkSynAssign (SynExpr.Ident fldId) (SynExpr.Ident vId)
//let retInfo = match tyOpt with None -> None | Some ty -> Some (SynReturnInfo((ty, SynInfo.unnamedRetVal), ty.Range))
let binding = mkSynBinding (xmlDoc, headPat) (access, false, false, mMemberPortion, DebugPointAtBinding.NoneAtInvisible, None, rhsExpr, rhsExpr.Range, [], [], Some (memberFlags SynMemberKind.PropertySet), SynBindingTrivia.Zero)
Expand Down
22 changes: 14 additions & 8 deletions src/fsharp/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2345,10 +2345,10 @@ let ComputeInlineFlag (memFlagsOption: SynMemberFlags option) isInline isMutable
// name-resolution-sensitive adjustments to the syntax tree.
//
// One part of this "normalization" ensures:
// "let SynPat.LongIdent(f) = e" when f not a datatype constructor --> let Pat_var(f) = e"
// "let SynPat.LongIdent(f) pat = e" when f not a datatype constructor --> let Pat_var(f) = \pat. e"
// "let (SynPat.LongIdent(f) : ty) = e" when f not a datatype constructor --> let (Pat_var(f) : ty) = e"
// "let (SynPat.LongIdent(f) : ty) pat = e" when f not a datatype constructor --> let (Pat_var(f) : ty) = \pat. e"
// "let SynPat.ParametersOwner(f) = e" when f not a datatype constructor --> let Pat_var(f) = e"
// "let SynPat.ParametersOwner(f) pat = e" when f not a datatype constructor --> let Pat_var(f) = \pat. e"
// "let (SynPat.ParametersOwner(f) : ty) = e" when f not a datatype constructor --> let (Pat_var(f) : ty) = e"
// "let (SynPat.ParametersOwner(f) : ty) pat = e" when f not a datatype constructor --> let (Pat_var(f) : ty) = \pat. e"
//
// This is because the first lambda in a function definition "let F x = e"
// now looks like a constructor application, i.e. let (F x) = e ...
Expand Down Expand Up @@ -2474,7 +2474,7 @@ module BindingNormalization =
// of available items, to the point that you can't even define a function with the same name as an existing union case.
match pat with
| SynPat.FromParseError(p, _) -> normPattern p
| SynPat.LongIdent (LongIdentWithDots(longId, _), _, toolId, tyargs, SynArgPats.Pats args, vis, m) ->
| SynPat.ParametersOwner (LongIdentInParametersOwnerNamePat longId, _, toolId, tyargs, SynArgPats.Pats args, vis, m) ->
let typars = match tyargs with None -> inferredTyparDecls | Some typars -> typars
match memberFlagsOpt with
| None ->
Expand Down Expand Up @@ -5079,7 +5079,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p
let pats', acc = TcPatterns warnOnUpper cenv env vFlags (tpenv, names, takenNames) (List.map (fun _ -> ty) pats) pats
(fun values -> TPat_conjs(List.map (fun f -> f values) pats', m)), acc

| SynPat.LongIdent (longDotId=longDotId; typarDecls=tyargs; argPats=args; accessibility=vis; range=m) ->
| SynPat.ParametersOwner (namePat = LongIdentWithDotsInParametersOwnerNamePat longDotId; typarDecls=tyargs; argPats=args; accessibility=vis; range=m) ->
TcPatLongIdent warnOnUpper cenv env ad topValInfo vFlags (tpenv, names, takenNames) ty (longDotId, tyargs, args, vis, m)

| SynPat.QuoteExpr(_, m) ->
Expand Down Expand Up @@ -5142,6 +5142,11 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p
| SynPat.FromParseError (pat, _) ->
suppressErrorReporting (fun () -> TcPatAndRecover warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) (NewErrorType()) pat)

| SynPat.Ident (range = m)
| SynPat.LongIdent (range = m) ->
// TODO: this probably is a bad way of dealing with this...
error(Error((9002,"Unexpected patterns to be typed checked"), m))

and CheckNoArgsForLiteral args m =
match args with
| SynArgPats.Pats []
Expand Down Expand Up @@ -5169,7 +5174,8 @@ and ConvSynPatToSynExpr x =
| SynPat.Const (c, m) -> SynExpr.Const (c, m)
| SynPat.Named (id, _, None, _) -> SynExpr.Ident id
| SynPat.Typed (p, cty, m) -> SynExpr.Typed (ConvSynPatToSynExpr p, cty, m)
| SynPat.LongIdent (longDotId=LongIdentWithDots(longId, dotms) as lidwd; argPats=args; accessibility=None; range=m) ->
| SynPat.ParametersOwner (namePat = LongIdentWithDotsInParametersOwnerNamePat lidwd; argPats=args; accessibility=None; range=m) ->
let (LongIdentWithDots(longId, dotms)) = lidwd
let args = match args with SynArgPats.Pats args -> args | _ -> failwith "impossible: active patterns can be used only with SynConstructorArgs.Pats"
let e =
if dotms.Length = longId.Length then
Expand Down Expand Up @@ -10099,7 +10105,7 @@ and CheckRecursiveBindingIds binds =
match b with
| SynPat.Named(id, _, _, _)
| SynPat.As(_, SynPat.Named(id, _, _, _), _)
| SynPat.LongIdent(longDotId=LongIdentWithDots([id], _)) -> id.idText
| SynPat.ParametersOwner(namePat=SingleIdentInParametersOwnerNamePat id) -> id.idText
| _ -> ""
if nm <> "" && not (hashOfBinds.Add nm) then
error(Duplicate("value", nm, m))
Expand Down
12 changes: 11 additions & 1 deletion src/fsharp/SyntaxTree.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1100,8 +1100,16 @@ type SynPat =
rhsPat: SynPat *
range: range

| Ident of
ident: Ident *
range: range

| LongIdent of
longDotId: LongIdentWithDots *
range: range

| ParametersOwner of
namePat: SynPat *
propertyKeyword: PropertyKeyword option *
extraId: Ident option * // holds additional ident for tooling
typarDecls: SynValTyparDecls option * // usually None: temporary used to parse "f<'a> x = x"
Expand Down Expand Up @@ -1166,7 +1174,9 @@ type SynPat =
| SynPat.Or (range=m)
| SynPat.Ands (range=m)
| SynPat.As (range=m)
| SynPat.LongIdent (range=m)
| SynPat.Ident(range=m)
| SynPat.LongIdent(range=m)
| SynPat.ParametersOwner (range=m)
| SynPat.ArrayOrList (range=m)
| SynPat.Tuple (range=m)
| SynPat.Typed (range=m)
Expand Down
13 changes: 12 additions & 1 deletion src/fsharp/SyntaxTree.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -1232,9 +1232,20 @@ type SynPat =
rhsPat: SynPat *
range: range

/// A long identifier pattern possibly with argument patterns
/// Used as namePat in ParametersOwner
| Ident of
ident: Ident *
range: range

/// Used as namePat in ParametersOwner
| LongIdent of
longDotId: LongIdentWithDots *
range: range

/// A long identifier pattern possibly with argument patterns
| ParametersOwner of
/// Can be SynPat.Ident or SynPat.LongIdent
namePat: SynPat *
propertyKeyword: PropertyKeyword option *
extraId: Ident option * // holds additional ident for tooling
typarDecls: SynValTyparDecls option * // usually None: temporary used to parse "f<'a> x = x"
Expand Down
45 changes: 38 additions & 7 deletions src/fsharp/SyntaxTreeOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,24 @@ let (|SingleIdent|_|) inp =
| SynExpr.Ident id -> Some id
| _ -> None

let (|SingleIdentInParametersOwnerNamePat|_|) (namePat:SynPat) =
match namePat with
| SynPat.Ident(ident, _)
| SynPat.LongIdent(longDotId = LongIdentWithDots([ident], _)) -> Some ident
| _ -> None

let (|LongIdentInParametersOwnerNamePat|) (namePat:SynPat) =
match namePat with
| SynPat.Ident(ident, _) -> [ident]
| SynPat.LongIdent(longDotId = LongIdentWithDots(lids, _)) -> lids
| _ -> []

let (|LongIdentWithDotsInParametersOwnerNamePat|) (namePat: SynPat) =
match namePat with
| SynPat.Ident(ident, _) -> LongIdentWithDots([ident], [])
| SynPat.LongIdent(longIdentWithDots, _) -> longIdentWithDots
| _ -> LongIdentWithDots([], [])

let (|SynBinOp|_|) input =
match input with
| SynExpr.App (ExprAtomicFlag.NonAtomic, false, SynExpr.App (ExprAtomicFlag.NonAtomic, true, SynExpr.Ident synId, x1, _m1), x2, _m2) ->
Expand Down Expand Up @@ -137,7 +155,7 @@ let rec IsControlFlowExpression e =
//
// For example
// let x = 1 + 1
// gets extended to inludde the 'let x'.
// gets extended to include the 'let x'.
//
// A corner case: some things that look like simple value bindings get generalized, e.g.
// let empty = []
Expand All @@ -150,7 +168,7 @@ let IsDebugPointBinding synPat synExpr =
// Don't yield the binding sequence point if there are any arguments, i.e. we're defining a function or a method
let isFunction =
match synPat with
| SynPat.LongIdent (argPats=SynArgPats.Pats args; typarDecls=typarDecls) when not args.IsEmpty || typarDecls.IsSome -> true
| SynPat.ParametersOwner (argPats=SynArgPats.Pats args; typarDecls=typarDecls) when not args.IsEmpty || typarDecls.IsSome -> true
| _ -> false
not isFunction

Expand All @@ -165,12 +183,12 @@ let mkSynPatVar vis (id: Ident) = SynPat.Named (id, false, vis, id.idRange)

let mkSynThisPatVar (id: Ident) = SynPat.Named (id, true, None, id.idRange)

let mkSynPatMaybeVar lidwd vis m = SynPat.LongIdent (lidwd, None, None, None, SynArgPats.Pats [], vis, m)
let mkSynPatMaybeVar namePat vis m = SynPat.ParametersOwner (namePat, None, None, None, SynArgPats.Pats [], vis, m)

/// Extract the argument for patterns corresponding to the declaration of 'new ... = ...'
let (|SynPatForConstructorDecl|_|) x =
match x with
| SynPat.LongIdent (longDotId=LongIdentWithDots([_], _); argPats=SynArgPats.Pats [arg]) -> Some arg
| SynPat.ParametersOwner (namePat=SingleIdentInParametersOwnerNamePat _; argPats=SynArgPats.Pats [arg]) -> Some arg
| _ -> None

/// Recognize the '()' in 'new()'
Expand Down Expand Up @@ -224,7 +242,7 @@ let rec SimplePatOfPat (synArgNameGenerator: SynArgNameGenerator) p =
let m = p.Range
let isCompGen, altNameRefCell, id, item =
match p with
| SynPat.LongIdent(longDotId=LongIdentWithDots([id], _); typarDecls=None; argPats=SynArgPats.Pats []; accessibility=None) ->
| SynPat.ParametersOwner(namePat=SingleIdentInParametersOwnerNamePat id; typarDecls=None; argPats=SynArgPats.Pats []; accessibility=None) ->
// The pattern is 'V' or some other capitalized identifier.
// It may be a real variable, in which case we want to maintain its name.
// But it may also be a nullary union case or some other identifier.
Expand Down Expand Up @@ -599,12 +617,12 @@ module SynInfo =

let infosForExplicitArgs =
match pat with
| Some(SynPat.LongIdent(argPats=SynArgPats.Pats curriedArgs)) -> List.map InferSynArgInfoFromPat curriedArgs
| Some(SynPat.ParametersOwner(argPats=SynArgPats.Pats curriedArgs)) -> List.map InferSynArgInfoFromPat curriedArgs
| _ -> []

let explicitArgsAreSimple =
match pat with
| Some(SynPat.LongIdent(argPats=SynArgPats.Pats curriedArgs)) -> List.forall isSimplePattern curriedArgs
| Some(SynPat.ParametersOwner(argPats=SynArgPats.Pats curriedArgs)) -> List.forall isSimplePattern curriedArgs
| _ -> true

let retInfo = InferSynReturnData retInfo
Expand Down Expand Up @@ -888,3 +906,16 @@ let (|ParsedHashDirectiveArguments|) (input: ParsedHashDirectiveArgument list) =
| ParsedHashDirectiveArgument.String (s, _, _) -> s
| ParsedHashDirectiveArgument.SourceIdentifier (_, v, _) -> v)
input

let prependIdentInPattern (ident: Ident) (dotm: range) (pat: SynPat): SynPat =
let m = unionRanges ident.idRange pat.Range

match pat with
| SynPat.Ident (ident=lastIdent) ->
SynPat.LongIdent(LongIdentWithDots([ ident; lastIdent ], [ dotm ]), m)
| SynPat.LongIdent(LongIdentWithDots(lids, dots), _) ->
SynPat.LongIdent(LongIdentWithDots(ident::lids, dotm::dots), m)
| _ ->
// TODO: create specific error?
errorR(Error((9001, "Unexpected pattern in prependIdentInPattern"), m))
SynPat.Const(SynConst.Unit, m)
10 changes: 9 additions & 1 deletion src/fsharp/SyntaxTreeOps.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ val (|LongOrSingleIdent|_|): inp:SynExpr -> (bool * LongIdentWithDots * SynSimpl

val (|SingleIdent|_|): inp:SynExpr -> Ident option

val (|SingleIdentInParametersOwnerNamePat|_|): namePat:SynPat -> Ident option

val (|LongIdentInParametersOwnerNamePat|): namePat:SynPat -> LongIdent

val (|LongIdentWithDotsInParametersOwnerNamePat|): namePat: SynPat -> LongIdentWithDots

/// This affects placement of debug points
val IsControlFlowExpression: e:SynExpr -> bool

Expand All @@ -61,7 +67,7 @@ val mkSynPatVar: vis:SynAccess option -> id:Ident -> SynPat

val mkSynThisPatVar: id:Ident -> SynPat

val mkSynPatMaybeVar: lidwd:LongIdentWithDots -> vis:SynAccess option -> m:range -> SynPat
val mkSynPatMaybeVar: namePat: SynPat -> vis:SynAccess option -> m:range -> SynPat

val ( |SynPatForConstructorDecl|_| ): x:SynPat -> SynPat option

Expand Down Expand Up @@ -300,3 +306,5 @@ val (|SynPipeRight2|_|): SynExpr -> (SynExpr * SynExpr * SynExpr) option

/// 'e1 |||> e2'
val (|SynPipeRight3|_|): SynExpr -> (SynExpr * SynExpr * SynExpr * SynExpr) option

val prependIdentInPattern: ident: Ident -> dotm: range -> pat: SynPat -> SynPat
Loading