5
5
from abc import ABC , abstractmethod
6
6
from collections .abc import Container
7
7
from dataclasses import dataclass , field
8
+ from enum import Enum
8
9
from threading import RLock
9
- from typing import TYPE_CHECKING , Callable , List , Union , cast , final
10
+ from typing import TYPE_CHECKING , List , Union , cast , final
10
11
11
12
from ..cterm import CSubst , CTerm , cterm_build_claim , cterm_build_rule
12
13
from ..kast import EMPTY_ATT
41
42
_LOGGER : Final = logging .getLogger (__name__ )
42
43
43
44
45
+ class NodeAttr (Enum ):
46
+ ROOT = 'root'
47
+ VACUOUS = 'vacuous'
48
+ STUCK = 'stuck'
49
+ LEAF = 'leaf'
50
+ SPLIT = 'split'
51
+
52
+
44
53
class KCFGStore :
45
54
store_path : Path
46
55
@@ -79,21 +88,20 @@ def read_cfg_data(self) -> dict[str, Any]:
79
88
80
89
81
90
class KCFG (Container [Union ['KCFG.Node' , 'KCFG.Successor' ]]):
82
- checkers : dict [str , Callable [[NodeIdLike ], bool ]]
83
-
84
- def add_node_attr (self , attr_name : str , checker : Callable [[NodeIdLike ], bool ]) -> None :
85
- if attr_name in self .checkers :
86
- _LOGGER .warning (f'overriding attribute checking hook for { attr_name } .' )
87
- self .checkers [attr_name ] = checker
88
-
89
91
def compute_attrs (self , node_id : int ) -> None :
92
+ def check_root (_node_id : int ) -> bool :
93
+ return len (self .predecessors (_node_id )) == 0
94
+
90
95
node = self .node (node_id )
91
- node .attrs = [attr_name for attr_name , checker in self .checkers .items () if checker (node .id )]
96
+ node .clear_attrs ()
97
+
98
+ if check_root (node_id ):
99
+ node .add_attr (NodeAttr .ROOT )
92
100
93
101
class Node :
94
102
id : int
95
103
cterm : CTerm
96
- attrs : list [ str ]
104
+ attrs : set [ NodeAttr ]
97
105
98
106
def __lt__ (self , other : Any ) -> bool :
99
107
if not isinstance (other , KCFG .Node ):
@@ -107,6 +115,15 @@ def __init__(self, id: int, cterm: CTerm) -> None:
107
115
def to_dict (self ) -> dict [str , Any ]:
108
116
return {'id' : self .id , 'cterm' : self .cterm .to_dict ()}
109
117
118
+ def add_attr (self , attr : NodeAttr ) -> None :
119
+ self .attrs .add (attr )
120
+
121
+ def remove_attr (self , attr : NodeAttr ) -> None :
122
+ self .attrs .remove (attr )
123
+
124
+ def clear_attrs (self ) -> None :
125
+ self .attrs .clear ()
126
+
110
127
class Successor (ABC ):
111
128
source : KCFG .Node
112
129
@@ -372,12 +389,6 @@ def __init__(self, cfg_dir: Path | None = None, optimize_memory: bool = True) ->
372
389
if cfg_dir is not None :
373
390
self ._kcfg_store = KCFGStore (cfg_dir )
374
391
375
- self .add_node_attr ('root' , self .is_root )
376
- self .add_node_attr ('vacious' , self .is_vacuous )
377
- self .add_node_attr ('stuck' , self .is_stuck )
378
- self .add_node_attr ('leaf' , self .is_leaf )
379
- self .add_node_attr ('split' , self .is_split )
380
-
381
392
def __contains__ (self , item : object ) -> bool :
382
393
if type (item ) is KCFG .Node :
383
394
return self .contains_node (item )
@@ -893,8 +904,7 @@ def remove_alias(self, alias: str) -> None:
893
904
self ._aliases .pop (alias )
894
905
895
906
def is_root (self , node_id : NodeIdLike ) -> bool :
896
- node_id = self ._resolve (node_id )
897
- return len (self .predecessors (node_id )) == 0
907
+ return NodeAttr .ROOT in self .node (node_id ).attrs
898
908
899
909
def is_vacuous (self , node_id : NodeIdLike ) -> bool :
900
910
node_id = self ._resolve (node_id )
0 commit comments