Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add trivia information to SynConst.Measure #15614

Merged
merged 16 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from 15 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
44 changes: 23 additions & 21 deletions src/Compiler/Checking/CheckExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -753,16 +753,16 @@ let ForNewConstructors tcSink (env: TcEnv) mObjTy methodName meths =
/// Typecheck rational constant terms in units-of-measure exponents
let rec TcSynRationalConst c =
match c with
| SynRationalConst.Integer i -> intToRational i
| SynRationalConst.Negate c2 -> NegRational (TcSynRationalConst c2)
| SynRationalConst.Rational(p, q, _) -> DivRational (intToRational p) (intToRational q)
| SynRationalConst.Integer(value = i) -> intToRational i
| SynRationalConst.Negate(rationalConst = c2) -> NegRational (TcSynRationalConst c2)
| SynRationalConst.Rational(numerator = p; denominator = q) -> DivRational (intToRational p) (intToRational q)

/// Typecheck constant terms in expressions and patterns
let TcConst (cenv: cenv) (overallTy: TType) m env synConst =
let g = cenv.g
let rec tcMeasure ms =
match ms with
| SynMeasure.One -> Measure.One
| SynMeasure.One _ -> Measure.One
| SynMeasure.Named(tc, m) ->
let ad = env.eAccessRights
let _, tcref = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurence.Use OpenQualified env.eNameResEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No)
Expand All @@ -774,9 +774,11 @@ let TcConst (cenv: cenv) (overallTy: TType) m env synConst =
| SynMeasure.Product(ms1, ms2, _) -> Measure.Prod(tcMeasure ms1, tcMeasure ms2)
| SynMeasure.Divide(ms1, (SynMeasure.Seq (_ :: _ :: _, _) as ms2), m) ->
warning(Error(FSComp.SR.tcImplicitMeasureFollowingSlash(), m))
Measure.Prod(tcMeasure ms1, Measure.Inv (tcMeasure ms2))
let factor1 = ms1 |> Option.defaultValue (SynMeasure.One Range.Zero)
Measure.Prod(tcMeasure factor1, Measure.Inv (tcMeasure ms2))
| SynMeasure.Divide(ms1, ms2, _) ->
Measure.Prod(tcMeasure ms1, Measure.Inv (tcMeasure ms2))
let factor1 = ms1 |> Option.defaultValue (SynMeasure.One Range.Zero)
Measure.Prod(tcMeasure factor1, Measure.Inv (tcMeasure ms2))
| SynMeasure.Seq(mss, _) -> ProdMeasures (List.map tcMeasure mss)
| SynMeasure.Anon _ -> error(Error(FSComp.SR.tcUnexpectedMeasureAnon(), m))
| SynMeasure.Var(_, m) -> error(Error(FSComp.SR.tcNonZeroConstantCannotHaveGenericUnit(), m))
Expand All @@ -787,10 +789,10 @@ let TcConst (cenv: cenv) (overallTy: TType) m env synConst =
let unifyMeasureArg iszero tcr =
let measureTy =
match synConst with
| SynConst.Measure(_, _, SynMeasure.Anon _) ->
| SynConst.Measure(synMeasure = SynMeasure.Anon _) ->
(mkAppTy tcr [TType_measure (Measure.Var (NewAnonTypar (TyparKind.Measure, m, TyparRigidity.Anon, (if iszero then TyparStaticReq.None else TyparStaticReq.HeadType), TyparDynamicReq.No)))])

| SynConst.Measure(_, _, ms) -> mkAppTy tcr [TType_measure (tcMeasure ms)]
| SynConst.Measure(synMeasure = ms) -> mkAppTy tcr [TType_measure (tcMeasure ms)]
| _ -> mkAppTy tcr [TType_measure Measure.One]
unif measureTy

Expand Down Expand Up @@ -843,43 +845,43 @@ let TcConst (cenv: cenv) (overallTy: TType) m env synConst =
| SynConst.UIntPtr i ->
unif g.unativeint_ty
Const.UIntPtr i
| SynConst.Measure(SynConst.Single f, _, _) ->
| SynConst.Measure(constant = SynConst.Single f) ->
unifyMeasureArg (f=0.0f) g.pfloat32_tcr
Const.Single f
| SynConst.Measure(SynConst.Double f, _, _) ->
| SynConst.Measure(constant = SynConst.Double f) ->
unifyMeasureArg (f=0.0) g.pfloat_tcr
Const.Double f
| SynConst.Measure(SynConst.Decimal f, _, _) ->
| SynConst.Measure(constant = SynConst.Decimal f) ->
unifyMeasureArg false g.pdecimal_tcr
Const.Decimal f
| SynConst.Measure(SynConst.SByte i, _, _) ->
| SynConst.Measure(constant = SynConst.SByte i)->
unifyMeasureArg (i=0y) g.pint8_tcr
Const.SByte i
| SynConst.Measure(SynConst.Int16 i, _, _) ->
| SynConst.Measure(constant = SynConst.Int16 i) ->
unifyMeasureArg (i=0s) g.pint16_tcr
Const.Int16 i
| SynConst.Measure(SynConst.Int32 i, _, _) ->
| SynConst.Measure(constant = SynConst.Int32 i) ->
unifyMeasureArg (i=0) g.pint_tcr
Const.Int32 i
| SynConst.Measure(SynConst.Int64 i, _, _) ->
| SynConst.Measure(constant = SynConst.Int64 i) ->
unifyMeasureArg (i=0L) g.pint64_tcr
Const.Int64 i
| SynConst.Measure(SynConst.IntPtr i, _, _) when expandedMeasurablesEnabled ->
| SynConst.Measure(constant = SynConst.IntPtr i) when expandedMeasurablesEnabled ->
unifyMeasureArg (i=0L) g.pnativeint_tcr
Const.IntPtr i
| SynConst.Measure(SynConst.Byte i, _, _) when expandedMeasurablesEnabled ->
| SynConst.Measure(constant = SynConst.Byte i) when expandedMeasurablesEnabled ->
unifyMeasureArg (i=0uy) g.puint8_tcr
Const.Byte i
| SynConst.Measure(SynConst.UInt16 i, _, _) when expandedMeasurablesEnabled ->
| SynConst.Measure(constant = SynConst.UInt16 i) when expandedMeasurablesEnabled ->
unifyMeasureArg (i=0us) g.puint16_tcr
Const.UInt16 i
| SynConst.Measure(SynConst.UInt32 i, _, _) when expandedMeasurablesEnabled ->
| SynConst.Measure(constant = SynConst.UInt32 i) when expandedMeasurablesEnabled ->
unifyMeasureArg (i=0u) g.puint_tcr
Const.UInt32 i
| SynConst.Measure(SynConst.UInt64 i, _, _) when expandedMeasurablesEnabled ->
| SynConst.Measure(constant = SynConst.UInt64 i) when expandedMeasurablesEnabled ->
unifyMeasureArg (i=0UL) g.puint64_tcr
Const.UInt64 i
| SynConst.Measure(SynConst.UIntPtr i, _, _) when expandedMeasurablesEnabled ->
| SynConst.Measure(constant = SynConst.UIntPtr i) when expandedMeasurablesEnabled ->
unifyMeasureArg (i=0UL) g.punativeint_tcr
Const.UIntPtr i
| SynConst.Char c ->
Expand Down
6 changes: 3 additions & 3 deletions src/Compiler/Service/ServiceInterfaceStubGenerator.fs
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ type InterfaceData =
| InterfaceData.ObjExpr (StripParenTypes ty, _) ->
let rec (|RationalConst|) =
function
| SynRationalConst.Integer i -> string i
| SynRationalConst.Rational (numerator, denominator, _) -> sprintf "(%i/%i)" numerator denominator
| SynRationalConst.Negate (RationalConst s) -> sprintf "- %s" s
| SynRationalConst.Integer (value = i) -> string i
| SynRationalConst.Rational (numerator = numerator; denominator = denominator) -> sprintf "(%i/%i)" numerator denominator
| SynRationalConst.Negate (rationalConst = (RationalConst s)) -> sprintf "- %s" s

let rec (|TypeIdent|_|) =
function
Expand Down
10 changes: 6 additions & 4 deletions src/Compiler/Service/ServiceParsedInputOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1838,21 +1838,23 @@ module ParsedInput =
List.iter walkType ts
walkMemberSig sign
walkExpr e
| SynExpr.Const (SynConst.Measure (_, _, m), _) -> walkMeasure m
| SynExpr.Const(constant = SynConst.Measure (synMeasure = m)) -> walkMeasure m
| _ -> ()

and walkMeasure measure =
match measure with
| SynMeasure.Product (m1, m2, _)
| SynMeasure.Divide (m1, m2, _) ->
| SynMeasure.Product (m1, m2, _) ->
walkMeasure m1
walkMeasure m2
| SynMeasure.Divide (m1, m2, _) ->
m1 |> Option.iter walkMeasure
walkMeasure m2
| SynMeasure.Named (longIdent, _) -> addLongIdent longIdent
| SynMeasure.Seq (ms, _) -> List.iter walkMeasure ms
| SynMeasure.Paren (m, _)
| SynMeasure.Power (m, _, _) -> walkMeasure m
| SynMeasure.Var (ty, _) -> walkTypar ty
| SynMeasure.One
| SynMeasure.One _
| SynMeasure.Anon _ -> ()

and walkSimplePat spat =
Expand Down
12 changes: 6 additions & 6 deletions src/Compiler/SyntaxTree/SyntaxTree.fs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ type SynConst =

| UInt16s of uint16[]

| Measure of constant: SynConst * constantRange: range * SynMeasure
| Measure of constant: SynConst * constantRange: range * synMeasure: SynMeasure * trivia: SynMeasureConstantTrivia

| SourceIdentifier of constant: string * value: string * range: range

Expand All @@ -178,11 +178,11 @@ type SynMeasure =

| Seq of measures: SynMeasure list * range: range

| Divide of measure1: SynMeasure * measure2: SynMeasure * range: range
| Divide of measure1: SynMeasure option * measure2: SynMeasure * range: range

| Power of measure: SynMeasure * power: SynRationalConst * range: range

| One
| One of range: range

| Anon of range: range

Expand All @@ -193,11 +193,11 @@ type SynMeasure =
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynRationalConst =

| Integer of value: int32
| Integer of value: int32 * range: range

| Rational of numerator: int32 * denominator: int32 * range: range
| Rational of numerator: int32 * numeratorRange: range * denominator: int32 * denominatorRange: range * range: range

| Negate of SynRationalConst
| Negate of rationalConst: SynRationalConst * range: range

[<RequireQualifiedAccess>]
type SynAccess =
Expand Down
12 changes: 6 additions & 6 deletions src/Compiler/SyntaxTree/SyntaxTree.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ type SynConst =
| UInt16s of uint16[]

/// Old comment: "we never iterate, so the const here is not another SynConst.Measure"
| Measure of constant: SynConst * constantRange: range * SynMeasure
| Measure of constant: SynConst * constantRange: range * synMeasure: SynMeasure * trivia: SynMeasureConstantTrivia

/// Source Line, File, and Path Identifiers
/// Containing both the original value as the evaluated value.
Expand All @@ -193,13 +193,13 @@ type SynMeasure =
| Seq of measures: SynMeasure list * range: range

/// A division of two units of measure, e.g. 'kg / m'
| Divide of measure1: SynMeasure * measure2: SynMeasure * range: range
| Divide of measure1: SynMeasure option * measure2: SynMeasure * range: range

/// A power of a unit of measure, e.g. 'kg ^ 2'
| Power of measure: SynMeasure * power: SynRationalConst * range: range
dawedawe marked this conversation as resolved.
Show resolved Hide resolved

/// The '1' unit of measure
| One
| One of range: range

/// An anonymous (inferred) unit of measure
| Anon of range: range
Expand All @@ -214,11 +214,11 @@ type SynMeasure =
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynRationalConst =

| Integer of value: int32
| Integer of value: int32 * range: range

| Rational of numerator: int32 * denominator: int32 * range: range
| Rational of numerator: int32 * numeratorRange: range * denominator: int32 * denominatorRange: range * range: range

| Negate of SynRationalConst
| Negate of rationalConst: SynRationalConst * range: range

/// Represents an accessibility modifier in F# syntax
[<RequireQualifiedAccess>]
Expand Down
7 changes: 7 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTrivia.fs
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,10 @@ type SynMemberSigMemberTrivia =
}

static member Zero: SynMemberSigMemberTrivia = { GetSetKeywords = None }

[<NoEquality; NoComparison>]
type SynMeasureConstantTrivia =
{
LessRange: range
GreaterRange: range
}
6 changes: 6 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTrivia.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -507,3 +507,9 @@ type SynMemberSigMemberTrivia =
}

static member Zero: SynMemberSigMemberTrivia

/// Represents additional information for SynConst.Measure
[<NoEquality; NoComparison>]
type SynMeasureConstantTrivia =
{ LessRange: range
GreaterRange: range }
52 changes: 37 additions & 15 deletions src/Compiler/pars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -3278,25 +3278,25 @@ rationalConstant:
{ if $2 <> "/" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure())
if fst $3 = 0 then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsIllegalDenominatorForMeasureExponent())
if (snd $1) || (snd $3) then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs parseState))
SynRationalConst.Rational(fst $1, fst $3, lhs parseState) }
SynRationalConst.Rational(fst $1, rhs parseState 1, fst $3, rhs parseState 3, lhs parseState) }

| MINUS INT32 INFIX_STAR_DIV_MOD_OP INT32
{ if $3 <> "/" then reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure())
if fst $4 = 0 then reportParseErrorAt (rhs parseState 4) (FSComp.SR.parsIllegalDenominatorForMeasureExponent())
if (snd $2) || (snd $4) then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs parseState))
SynRationalConst.Negate(SynRationalConst.Rational(fst $2, fst $4, lhs parseState)) }
SynRationalConst.Negate(SynRationalConst.Rational(fst $2, rhs parseState 2, fst $4, rhs parseState 4, lhs parseState), lhs parseState) }

| INT32
{ if snd $1 then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs parseState))
SynRationalConst.Integer(fst $1) }
SynRationalConst.Integer(fst $1, lhs parseState) }

| MINUS INT32
{ if snd $2 then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs parseState))
SynRationalConst.Negate(SynRationalConst.Integer(fst $2)) }
SynRationalConst.Negate(SynRationalConst.Integer(fst $2, lhs parseState), lhs parseState) }
psfinaki marked this conversation as resolved.
Show resolved Hide resolved

atomicUnsignedRationalConstant:
| INT32 { if snd $1 then errorR(Error(FSComp.SR.lexOutsideThirtyTwoBitSigned(), lhs parseState))
SynRationalConst.Integer(fst $1) }
SynRationalConst.Integer(fst $1, lhs parseState) }

| LPAREN rationalConstant rparen
{ $2 }
Expand All @@ -3305,14 +3305,17 @@ atomicRationalConstant:
| atomicUnsignedRationalConstant { $1 }

| MINUS atomicUnsignedRationalConstant
{ SynRationalConst.Negate($2) }
{ SynRationalConst.Negate($2, lhs parseState) }

constant:
| rawConstant
{ $1, rhs parseState 1 }

| rawConstant HIGH_PRECEDENCE_TYAPP measureTypeArg
{ SynConst.Measure($1, rhs parseState 1, $3), lhs parseState }
{ let synMeasure, trivia = $3
let mConstant = rhs parseState 1
let m = unionRanges mConstant trivia.GreaterRange
SynConst.Measure($1, rhs parseState 1, synMeasure, trivia), m }

bindingPattern:
| headBindingPattern
Expand Down Expand Up @@ -5839,7 +5842,11 @@ appTypeCon:
appTypeConPower:
| appTypeCon INFIX_AT_HAT_OP atomicRationalConstant
{ if $2 <> "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedInfixOperator())
if $2 = "^-" then SynType.MeasurePower($1, SynRationalConst.Negate($3), lhs parseState)
if $2 = "^-" then
let afterMinus = (rhs parseState 2).EndRange
let beforeMinus = mkRange afterMinus.FileName (mkPos afterMinus.EndLine (afterMinus.EndColumn - 1)) afterMinus.End
let m = unionRanges beforeMinus (rhs parseState 3) // include MINUS in Negate range
SynType.MeasurePower($1, SynRationalConst.Negate($3, m), lhs parseState)
else SynType.MeasurePower($1, $3, lhs parseState) }

| appTypeCon
Expand Down Expand Up @@ -5996,7 +6003,11 @@ powerType:

| atomTypeOrAnonRecdType INFIX_AT_HAT_OP atomicRationalConstant
{ if $2 <> "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedInfixOperator())
if $2 = "^-" then SynType.MeasurePower($1, SynRationalConst.Negate($3), lhs parseState)
if $2 = "^-" then
let afterMinus = (rhs parseState 2).EndRange
let beforeMinus = mkRange afterMinus.FileName (mkPos afterMinus.EndLine (afterMinus.EndColumn - 1)) afterMinus.End
let m = unionRanges beforeMinus (rhs parseState 3) // include MINUS in Negate range
SynType.MeasurePower($1, SynRationalConst.Negate($3, m), lhs parseState)
else SynType.MeasurePower($1, $3, lhs parseState) }


Expand Down Expand Up @@ -6189,10 +6200,16 @@ dummyTypeArg:

measureTypeArg:
| LESS measureTypeExpr GREATER
{ $2 }
{ let mLess = rhs parseState 1
let mGreater = rhs parseState 3
let trivia = { LessRange = mLess; GreaterRange = mGreater }
$2, trivia }

| LESS UNDERSCORE GREATER
{ SynMeasure.Anon(lhs parseState) }
{ let mLess = rhs parseState 1
let mGreater = rhs parseState 3
let trivia = { LessRange = mLess; GreaterRange = mGreater }
SynMeasure.Anon(rhs parseState 2), trivia }

measureTypeAtom:
| path
Expand All @@ -6211,12 +6228,17 @@ measureTypePower:

| measureTypeAtom INFIX_AT_HAT_OP atomicRationalConstant
{ if $2 <> "^" && $2 <> "^-" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure())
if $2 = "^-" then SynMeasure.Power($1, SynRationalConst.Negate($3), lhs parseState)
if $2 = "^-" then
let afterMinus = (rhs parseState 2).EndRange
let beforeMinus = mkRange afterMinus.FileName (mkPos afterMinus.EndLine (afterMinus.EndColumn - 1)) afterMinus.End
let m = unionRanges beforeMinus (rhs parseState 3) // include MINUS in Negate range
SynMeasure.Power($1, SynRationalConst.Negate($3, m), lhs parseState)
else SynMeasure.Power($1, $3, lhs parseState) }

| INT32
{ if fst $1 <> 1 then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedIntegerLiteralForUnitOfMeasure())
SynMeasure.One }
let m = rhs parseState 1
SynMeasure.One(m) }

measureTypeSeq:
| measureTypePower
Expand All @@ -6235,11 +6257,11 @@ measureTypeExpr:
| measureTypeExpr INFIX_STAR_DIV_MOD_OP measureTypeExpr
{ if $2 <> "*" && $2 <> "/" then reportParseErrorAt (rhs parseState 2) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure())
if $2 = "*" then SynMeasure.Product($1, $3, lhs parseState)
else SynMeasure.Divide($1, $3, lhs parseState) }
else SynMeasure.Divide(Some $1, $3, lhs parseState) }

| INFIX_STAR_DIV_MOD_OP measureTypeExpr
{ if $1 <> "/" then reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnexpectedOperatorForUnitOfMeasure())
SynMeasure.Divide(SynMeasure.One, $2, lhs parseState) }
SynMeasure.Divide(None, $2, lhs parseState) }

typar:
| QUOTE ident
Expand Down
Loading
Loading