@@ -250,3 +250,183 @@ impl<T: Clone + Eq> MeetSemiLattice for FlatSet<T> {
250
250
true
251
251
}
252
252
}
253
+
254
+ macro_rules! packed_int_join_semi_lattice {
255
+ ( $name: ident, $base: ty) => {
256
+ #[ derive( Debug , PartialEq , Eq , Copy , Clone , PartialOrd , Ord ) ]
257
+ pub struct $name( $base) ;
258
+ impl $name {
259
+ pub const TOP : Self = Self ( <$base>:: MAX ) ;
260
+ // If the value is too large it will be top, which is more conservative and thus
261
+ // alright. It is only unsafe to make items bot.
262
+ #[ inline]
263
+ pub const fn new( v: $base) -> Self {
264
+ Self ( v)
265
+ }
266
+
267
+ #[ inline]
268
+ pub fn saturating_new( v: impl TryInto <$base>) -> Self {
269
+ v. try_into( ) . map( |v| Self ( v) ) . unwrap_or( Self :: TOP )
270
+ }
271
+
272
+ pub const fn inner( self ) -> $base {
273
+ self . 0
274
+ }
275
+ }
276
+
277
+ impl JoinSemiLattice for $name {
278
+ #[ inline]
279
+ fn join( & mut self , other: & Self ) -> bool {
280
+ match ( * self , * other) {
281
+ ( Self :: TOP , _) => false ,
282
+ ( a, b) if a == b => false ,
283
+ _ => {
284
+ * self = Self :: TOP ;
285
+ true
286
+ }
287
+ }
288
+ }
289
+ }
290
+
291
+ impl <C > crate :: fmt:: DebugWithContext <C > for $name {
292
+ fn fmt_with( & self , _: & C , f: & mut std:: fmt:: Formatter <' _>) -> std:: fmt:: Result {
293
+ if * self == Self :: TOP { write!( f, "TOP" ) } else { write!( f, "{}" , self . inner( ) ) }
294
+ }
295
+ }
296
+ } ;
297
+ }
298
+
299
+ packed_int_join_semi_lattice ! ( PackedU8JoinSemiLattice , u8 ) ;
300
+
301
+ #[ derive( Eq , PartialEq , Copy , Clone , Debug ) ]
302
+ pub struct FactArray < T , const N : usize > {
303
+ // FIXME(julianknodt): maybe map Idxs to each N element?
304
+ pub arr : [ T ; N ] ,
305
+ }
306
+
307
+ impl < T , const N : usize > FactArray < T , N > {
308
+ #[ inline]
309
+ pub fn insert ( & mut self , i : impl Idx , fact : T ) {
310
+ let Some ( v) = self . arr . get_mut ( i. index ( ) ) else { return } ;
311
+ * v = fact;
312
+ }
313
+ #[ inline]
314
+ pub fn get ( & self , i : & impl Idx ) -> Option < & T > {
315
+ self . arr . get ( i. index ( ) )
316
+ }
317
+ }
318
+
319
+ impl < T : JoinSemiLattice , const N : usize > JoinSemiLattice for FactArray < T , N > {
320
+ fn join ( & mut self , other : & Self ) -> bool {
321
+ let mut changed = false ;
322
+ for ( a, b) in self . arr . iter_mut ( ) . zip ( other. arr . iter ( ) ) {
323
+ changed |= a. join ( b) ;
324
+ }
325
+ changed
326
+ }
327
+ }
328
+
329
+ impl < T : MeetSemiLattice , const N : usize > MeetSemiLattice for FactArray < T , N > {
330
+ fn meet ( & mut self , other : & Self ) -> bool {
331
+ let mut changed = false ;
332
+ for ( a, b) in self . arr . iter_mut ( ) . zip ( other. arr . iter ( ) ) {
333
+ changed |= a. meet ( b) ;
334
+ }
335
+ changed
336
+ }
337
+ }
338
+
339
+ #[ derive( Eq , PartialEq , Copy , Clone , Debug ) ]
340
+ pub struct FactCache < I , L , F , const N : usize > {
341
+ facts : [ F ; N ] ,
342
+ ord : [ ( I , L ) ; N ] ,
343
+ len : usize ,
344
+ }
345
+
346
+ impl < I : Idx , L : Ord + Eq + Copy , F , const N : usize > FactCache < I , L , F , N > {
347
+ pub fn new ( empty_i : I , empty_l : L , empty_f : F ) -> Self
348
+ where
349
+ F : Copy ,
350
+ {
351
+ Self { facts : [ empty_f; N ] , ord : [ ( empty_i, empty_l) ; N ] , len : 0 }
352
+ }
353
+ /// inserts a fact into the cache, evicting the oldest one,
354
+ /// Or updating it if there is information on one already. If the new fact being
355
+ /// inserted is older than the previous fact, it will not be inserted.
356
+ pub fn insert ( & mut self , i : I , l : L , fact : F ) {
357
+ let mut idx = None ;
358
+ for ( j, ( ci, cl) ) in self . ord [ ..self . len ] . iter_mut ( ) . enumerate ( ) {
359
+ if * ci == i {
360
+ assert ! ( * cl <= l) ;
361
+ idx = Some ( j) ;
362
+ break ;
363
+ }
364
+ }
365
+ if idx. is_none ( ) && self . len < N {
366
+ let new_len = self . len + 1 ;
367
+ idx = Some ( std:: mem:: replace ( & mut self . len , new_len) ) ;
368
+ } ;
369
+ if let Some ( idx) = idx {
370
+ self . facts [ idx] = fact;
371
+ self . ord [ idx] = ( i, l) ;
372
+ return ;
373
+ } ;
374
+ let ( p, ( _, old_l) ) = self . ord . iter ( ) . enumerate ( ) . min_by_key ( |k| k. 1 . 1 ) . unwrap ( ) ;
375
+ // FIXME(julianknodt) maybe don't make this an assert but just don't update?
376
+ assert ! ( * old_l <= l) ;
377
+ self . ord [ p] = ( i, l) ;
378
+ self . facts [ p] = fact;
379
+ }
380
+ pub fn get ( & self , i : I ) -> Option < ( & L , & F ) > {
381
+ let ( p, ( _, loc) ) =
382
+ self . ord [ ..self . len ] . iter ( ) . enumerate ( ) . find ( |( _, iloc) | iloc. 0 == i) ?;
383
+ Some ( ( loc, & self . facts [ p] ) )
384
+ }
385
+ pub fn remove ( & mut self , i : I ) -> bool {
386
+ let Some ( pos) = self . ord [ ..self . len ] . iter ( ) . position ( |( ci, _) | * ci == i)
387
+ else { return false } ;
388
+
389
+ self . remove_idx ( pos) ;
390
+ return true ;
391
+ }
392
+ #[ inline]
393
+ fn remove_idx ( & mut self , i : usize ) {
394
+ assert ! ( i < self . len) ;
395
+ self . ord . swap ( i, self . len ) ;
396
+ self . facts . swap ( i, self . len ) ;
397
+ self . len -= 1 ;
398
+ }
399
+
400
+ fn drain_filter ( & mut self , mut should_rm : impl FnMut ( & I , & mut L , & mut F ) -> bool ) {
401
+ let mut i = 0 ;
402
+ while i < self . len {
403
+ let ( idx, l) = & mut self . ord [ i] ;
404
+ let f = & mut self . facts [ i] ;
405
+ if should_rm ( idx, l, f) {
406
+ self . remove_idx ( i) ;
407
+ continue ;
408
+ }
409
+ i += 1 ;
410
+ }
411
+ }
412
+ }
413
+
414
+ impl < I : Idx , L : Ord + Eq + Copy , F : Eq , const N : usize > JoinSemiLattice for FactCache < I , L , F , N > {
415
+ fn join ( & mut self , other : & Self ) -> bool {
416
+ let mut changed = false ;
417
+ self . drain_filter ( |i, l, f| {
418
+ let Some ( ( other_loc, other_fact) ) = other. get ( * i) else {
419
+ changed = true ;
420
+ return true ;
421
+ } ;
422
+ if other_fact == f {
423
+ * l = ( * l) . max ( * other_loc) ;
424
+ return false ;
425
+ }
426
+ changed = true ;
427
+ return true ;
428
+ } ) ;
429
+
430
+ changed
431
+ }
432
+ }
0 commit comments