@@ -770,13 +770,13 @@ def extractKwargsField (e : expr SourceRange)
770770partial def extractSubject (e : expr SourceRange)
771771 : SpecAssertionM (Option SpecExpr) := do
772772 match ← extractKwargsField e with
773- | some (kn, fn) => return some (.getIndex (.var kn) fn)
773+ | some (kn, fn) => return some (.getIndex (.var kn (loc := e.ann)) fn (loc := e.ann) )
774774 | none => pure ()
775775 match e with
776- | .Name _ ⟨_, name⟩ (.Load _) => return some (.var name)
776+ | .Name _ ⟨_, name⟩ (.Load _) => return some (.var name (loc := e.ann) )
777777 | .Subscript _ inner (.Constant _ (.ConString _ fieldName) _) (.Load _) =>
778778 match ← extractSubject inner with
779- | some subj => return some (.getIndex subj fieldName.val)
779+ | some subj => return some (.getIndex subj fieldName.val (loc := e.ann) )
780780 | none => return none
781781 | _ => return none
782782
@@ -790,7 +790,7 @@ def transCondition (e : expr SourceRange) : SpecAssertionM (Option SpecExpr) :=
790790 match ops.val[0 ] with
791791 | .In _ =>
792792 match ← extractSubject comparators.val[0 ] with
793- | some subj => return some (.containsKey subj key.val)
793+ | some subj => return some (.containsKey subj key.val (loc := e.ann) )
794794 | none => pure ()
795795 | _ => pure ()
796796 pure ()
@@ -800,7 +800,7 @@ def transCondition (e : expr SourceRange) : SpecAssertionM (Option SpecExpr) :=
800800/-- Run an action that may produce assertions, then wrap each new assertion's
801801 formula with `implies cond ...` (or `implies (not cond) ...` for else branches).
802802 If `cond` is `none`, assertions pass through unchanged. -/
803- def assumeCondition (cond : Option SpecExpr) (act : SpecAssertionM Unit)
803+ def assumeCondition (cond : Option SpecExpr) (loc : SourceRange) ( act : SpecAssertionM Unit)
804804 : SpecAssertionM Unit := do
805805 let prevAssertions := (←get).assertions
806806 modify fun s => { s with assertions := #[] }
@@ -809,7 +809,7 @@ def assumeCondition (cond : Option SpecExpr) (act : SpecAssertionM Unit)
809809 match cond with
810810 | some c =>
811811 let wrapped := newAssertions.map fun a =>
812- { a with formula := .implies c a.formula }
812+ { a with formula := .implies c a.formula loc }
813813 modify fun s => { s with assertions := prevAssertions ++ wrapped }
814814 | none =>
815815 modify fun s => { s with assertions := prevAssertions ++ newAssertions }
@@ -826,10 +826,10 @@ def transMessageExpr (e : expr SourceRange)
826826 | .Call _ (.Name _ funcName (.Load _)) args _ =>
827827 if funcName.val == " len" && args.val.size == 1 then
828828 match ← extractSubject args.val[0 ]! with
829- | some subj => return .len subj
830- | none => return .placeholder
831- else return .placeholder
832- | _ => return .placeholder
829+ | some subj => return .len subj (loc := e.ann)
830+ | none => return .placeholder (loc := e.ann)
831+ else return .placeholder (loc := e.ann)
832+ | _ => return .placeholder (loc := e.ann)
833833
834834/-- Look up a field in a TypedDict SpecType, returning its type if found. -/
835835def lookupTypedDictField (tp : SpecType) (field : String) : Option SpecType := do
@@ -951,24 +951,26 @@ private def makeComparison
951951 (isFloat isInt : Bool)
952952 (subj : SpecExpr) (bound : expr SourceRange)
953953 : SpecAssertionM (Option SpecExpr) := do
954+ let loc := bound.ann
954955 if isFloat then
955956 match extractFloatBound bound with
956- | some s => return some (floatCtor subj (.floatLit s))
957+ | some s => return some (floatCtor subj (.floatLit s (loc := loc) ))
957958 | none =>
958959 match extractIntBound bound with
959- | some n => return some (floatCtor subj (.floatLit (toString n)))
960+ | some n => return some (floatCtor subj (.floatLit (toString n) (loc := loc) ))
960961 | none => return none
961962 else if isInt then
962963 match extractIntBound bound with
963- | some n => return some (intCtor subj (.intLit n))
964+ | some n => return some (intCtor subj (.intLit n (loc := loc) ))
964965 | none => return none
965966 else
966967 match extractIntBound bound with
967- | some n => return some (intCtor subj (.intLit n))
968+ | some n => return some (intCtor subj (.intLit n (loc := loc) ))
968969 | none => return none
969970
970971def transAssertExpr (e : expr SourceRange)
971972 : SpecAssertionM SpecExpr := do
973+ let loc := e.ann
972974 -- isinstance(subject, T)
973975 match e with
974976 | .Call _ (.Name _ funcName (.Load _)) args _ =>
@@ -978,10 +980,10 @@ def transAssertExpr (e : expr SourceRange)
978980 | some subj =>
979981 match args.val[1 ] with
980982 | .Name _ typeName (.Load _) =>
981- return .isInstanceOf subj typeName.val
983+ return .isInstanceOf subj typeName.val (loc := loc)
982984 | _ =>
983985 specWarning e.ann s!" isinstance: unsupported type argument"
984- return .placeholder
986+ return .placeholder (loc := loc)
985987 | none => pure () -- fall through
986988 if funcName.val == " len" && args.val.size == 1 then
987989 -- This is just len(x), not a comparison; fall through
@@ -998,8 +1000,8 @@ def transAssertExpr (e : expr SourceRange)
9981000 match ← extractSubject callArgs.val[0 ] with
9991001 | some subj =>
10001002 match ops.val[0 ], extractIntBound comparators.val[0 ] with
1001- | .GtE _, some n => return .intGe (.len subj) (.intLit n)
1002- | .LtE _, some n => return .intLe (.len subj) (.intLit n)
1003+ | .GtE _, some n => return .intGe (.len subj (loc := loc)) (.intLit n (loc := comparators.val[ 0 ].ann)) (loc := loc )
1004+ | .LtE _, some n => return .intLe (.len subj (loc := loc)) (.intLit n (loc := comparators.val[ 0 ].ann)) (loc := loc )
10031005 | _, _ => pure ()
10041006 | none => pure ()
10051007 | _ => pure ()
@@ -1014,8 +1016,8 @@ def transAssertExpr (e : expr SourceRange)
10141016 let isFloat := subjType.any isFloatType
10151017 let isInt := subjType.any isIntType
10161018 let cmp ← match ops.val[0 ] with
1017- | .GtE _ => makeComparison .floatGe .intGe isFloat isInt subj comparators.val[0 ]
1018- | .LtE _ => makeComparison .floatLe .intLe isFloat isInt subj comparators.val[0 ]
1019+ | .GtE _ => makeComparison ( .floatGe · · (loc := loc)) ( .intGe · · (loc := loc)) isFloat isInt subj comparators.val[0 ]
1020+ | .LtE _ => makeComparison ( .floatLe · · (loc := loc)) ( .intLe · · (loc := loc)) isFloat isInt subj comparators.val[0 ]
10191021 | _ => pure none
10201022 match cmp with
10211023 | some expr => return expr
@@ -1025,7 +1027,7 @@ def transAssertExpr (e : expr SourceRange)
10251027 -- subject == "A" or subject == "B" or ...
10261028 match ← collectEnumValues e with
10271029 | some (subj, vals) =>
1028- return .enumMember subj vals
1030+ return .enumMember subj vals (loc := loc)
10291031 | none => pure ()
10301032 -- compile("pattern").search(subject) is not None
10311033 match e with
@@ -1044,14 +1046,14 @@ def transAssertExpr (e : expr SourceRange)
10441046 | some subj =>
10451047 match ops.val[0 ], comparators.val[0 ] with
10461048 | .IsNot _, .Constant _ (.ConNone _) _ =>
1047- return .regexMatch subj pattern.val
1049+ return .regexMatch subj pattern.val (loc := loc)
10481050 | _, _ => pure ()
10491051 | none => pure ()
10501052 | _ => pure ()
10511053 | _ => pure ()
10521054 -- Fallback: unrecognized pattern
10531055 specWarning e.ann s!" unrecognized assert pattern: {eformat e.toAst}"
1054- return .placeholder
1056+ return .placeholder (loc := loc)
10551057
10561058mutual
10571059
@@ -1113,7 +1115,7 @@ def blockStmt (s : stmt SourceRange) : SpecAssertionM Unit := do
11131115 blockStmts body.val
11141116 let bodyAssertions := (←get).assertions
11151117 let wrapped := bodyAssertions.map fun a =>
1116- { a with formula := .forallList listExpr varName a.formula }
1118+ { a with formula := .forallList listExpr varName a.formula s.ann }
11171119 modify fun s => { s with assertions := prevAssertions ++ wrapped }
11181120 | none =>
11191121 specWarning s.ann s!" For: cannot extract iterable expression"
@@ -1154,7 +1156,7 @@ def blockStmt (s : stmt SourceRange) : SpecAssertionM Unit := do
11541156 blockStmts body.val
11551157 let bodyAssertions := (←get).assertions
11561158 let wrapped := bodyAssertions.map fun a =>
1157- { a with formula := .forallDict dictSubj keyVar valVar a.formula }
1159+ { a with formula := .forallDict dictSubj keyVar valVar a.formula s.ann }
11581160 modify fun st => { st with assertions := prevAssertions ++ wrapped }
11591161 | none =>
11601162 specWarning s.ann s!" For: cannot extract dict expression"
@@ -1166,9 +1168,9 @@ def blockStmt (s : stmt SourceRange) : SpecAssertionM Unit := do
11661168 let cond ← transCondition pred
11671169 if cond.isNone then
11681170 specWarning pred.ann s!" if: unrecognized condition pattern: {eformat pred.toAst}"
1169- assumeCondition cond <| blockStmts t.val
1171+ assumeCondition cond pred.ann <| blockStmts t.val
11701172 if f.val.size > 0 then
1171- assumeCondition (cond.map .not) <| blockStmts f.val
1173+ assumeCondition (cond.map ( .not · pred.ann)) pred.ann <| blockStmts f.val
11721174 | .Pass _ =>
11731175 pure ()
11741176 | _ => specError s.ann s!" Unsupported statement: {eformat s.toAst}"
0 commit comments