22 | ----------------------------------
23 | --- Constructors recursiveness ---
24 | ----------------------------------
26 | ||| Weight info of recursive constructors
35 | ||| Either a constant (for non-recursive) or a function returning weight info (for recursive)
41 | export
46 | export
56 | export
66 | -- ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
67 | -- | \- directly recursive args
68 | -- \- `Left` for non-recursive, `Right` for recursive constructor
70 | -- determine if this type is a nat-or-list-like data, i.e. one which we can measure for the probability
83 | export
91 | -------------------------------------
92 | --- Getting (deriving) `ConsRecs` ---
93 | -------------------------------------
95 | -- This is a workaround of some bad and not yet understood behaviour, leading to both compile- and runtime errors
98 | workaroundFromNat = mapTTImp $ \e => case fst $ unAppAny e of IVar _ `{Data.Nat1.FromNat} => removeNamedApps e; _ => e
103 | -- this is a workaround for Idris compiler bug #2983
104 | export
108 | -- This function is moved out from `getConsRecs` to reduce the closure of the returned function
111 | guard $ weightableTy cons -- continue only when this type has structurally decreasing argument
114 | let inTyArg = arg $ foldl (\f, n => namedApp f n $ var n) .| var ty.name .| mapMaybe name ty.args
115 | let funSig = export' weightFunName $ piAll `(Data.Nat1.Nat1) $ map {piInfo := ImplicitArg} ty.args ++ [inTyArg]
119 | let lhsArgs : List (_, _) = mapI con.args $ \idx, arg => appArg arg <$> if contains idx wArgs && arg.count == MW
124 | patClause (var weightFunName .$ (reAppAny .| var con.name .| snd <$> lhsArgs)) $ case mapMaybe fst lhsArgs of
134 | -- TODO to think of better placement for this function; this anyway is intended to be called from the derived code.
142 | -- This function is moved out from `getConsRecs` to reduce the closure of the returned function
149 | cons <&> \(MkConRec con e) => (con,) $ MkConWeightInfo $ e <&> \(wMod, directRecConArgs) => do
151 | let directRecConArgArgs = flip mapMaybe con.args $ \conArg => case unAppAny conArg.type of (conArgTy, conArgArgs) => do
153 | -- default behaviour, spend fuel, weight proportional to fuel
154 | fromMaybe (SpendingFuel $ wMod . app `(Deriving.DepTyCheck.Gen.ConsRecs.leftDepth) . var) $ do
155 | -- work only with given args
156 | -- fail-fast if no given weightable args
158 | -- If for any weightable type argument (in `wTyArgs`) there exists a directly recursive constructor arg (in `directRecConArgs`) that has
159 | -- this type argument strictly decreasing, we consider this constructor to be non-fuel-spending.
161 | (decrTy, weightExpr) <- foldAlt' wTyArgs.asList $ \(wTyArg, weightTy, weightArgName) => map (weightTy,) $ do
167 | getAt wTyArg conArgArgs >>= getAppVar . getExpr >>= \arg => toMaybe .| contains arg freeNamesLessThanOrig .|
171 | weightableTyArgs : (consRecs : SortedMap Name (TypeInfo, List ConRec)) -> (ti : TypeInfo) -> SortedMap (Fin ti.args.length) (TypeInfo, Name)
173 | getAppVar ar.type >>= lookup' consRecs >>= \(wti, cons) => guard (weightableTy cons) >> (idx, wti,) <$> ar.name
175 | -- Builds `ConsRecs` only for the given types, assuming that given `NamesInfoInTypes` contains info for them and their dependencies
176 | getConsRecsFor : NamesInfoInTypes => Elaboration m => (desiredTypes : ListMap Name TypeInfo) -> m ConsRecs
178 | consRecs <- for (toSortedMap desiredTypes) $ \targetType => logBounds DetailedTrace "deptycheck.derive.consRec" [targetType] $ do
181 | w : Either Nat1 (TTImp -> TTImp, SortedSet $ Fin con.args.length) <- case isRecursive {containingType=Just targetType} con of
182 | -- ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ <- set of directly recursive constructor arguments
183 | -- \------ Modifier of the standard weight expression
188 | Just impl => quote (tuneWeight @{impl}) <&> \wm, expr => workaroundFromNat $ wm `applySyn` expr
189 | let directlyRecArgs : List $ Fin con.args.length := flip mapMaybe con.args.withIdx $ \idxarg => do
203 | export
207 | export
208 | lookupConsWithWeight : ConsRecs => NamesInfoInTypes => GenSignature -> Maybe $ List (Con, ConWeightInfo)
214 | export
218 | export
222 | -- Having a `ConsRecs` being built from the given `NamesInfoInTypes`,
223 | -- it'll get the updated `NamesInfoInTypes` and a `ConsRecs` equivalent to those being built from this `NamesInfoInTypes`, but more effective.
224 | export
225 | updateNamesAndConsRecs : NamesInfoInTypes => ConsRecs => Elaboration m => List TypeInfo -> m (NamesInfoInTypes, ConsRecs)
227 | newNiit <- logBounds Trace "deptycheck.derive.namesInfo.update" [] $ enrichNamesInfoInTypes tis niit
228 | newCr <- logBounds Trace "deptycheck.derive.consRec.update" [] $ map (crs <+>) $ getConsRecsFor @{newNiit} $ fromList $ tis <&> \ti => (ti.name, ti)