@@ -198,6 +198,10 @@ def visit_sequence_concatenation(self, node, tr_lhs, tr_rhs):
198198 def visit_record_access (self , node , tr_record ):
199199 assert isinstance (node , Record_Access )
200200
201+ @abstractmethod
202+ def visit_record_null_check (self , node , tr_record ):
203+ assert isinstance (node , Record_Null_Check )
204+
201205 @abstractmethod
202206 def visit_function_application (self , node , tr_function , tr_args ):
203207 assert isinstance (node , Function_Application )
@@ -353,7 +357,8 @@ def visit_record(self, node):
353357 assert isinstance (node , Record )
354358 self .logics .add ("datatypes" )
355359 for sort in node .components .values ():
356- sort .walk (self )
360+ if sort is not node :
361+ sort .walk (self )
357362
358363 def visit_boolean_literal (self , node , tr_sort ):
359364 assert isinstance (node , Boolean_Literal )
@@ -464,6 +469,10 @@ def visit_record_access(self, node, tr_record):
464469 assert isinstance (node , Record_Access )
465470 self .logics .add ("datatypes" )
466471
472+ def visit_record_null_check (self , node , tr_record ):
473+ assert isinstance (node , Record_Null_Check )
474+ self .logics .add ("datatypes" )
475+
467476 def visit_function_application (self , node , tr_function , tr_args ):
468477 assert isinstance (node , Function_Application )
469478 assert isinstance (tr_args , list )
@@ -763,23 +772,26 @@ def check_recursion_rec(self, visited):
763772class Record (Sort ):
764773 def __init__ (self , name ):
765774 super ().__init__ (name )
766- self .components = {}
775+ self .components = {}
776+ self .is_recursive = False
767777
768778 def add_component (self , name , sort ):
769779 assert isinstance (name , str )
770780 assert isinstance (sort , Sort )
771781 assert name not in self .components
772782
773783 self .components [name ] = sort
784+ self .is_recursive |= sort is self
774785
775786 def walk (self , visitor ):
776787 assert isinstance (visitor , Visitor )
777788 return visitor .visit_record (self )
778789
779790 def check_recursion_rec (self , visited ):
780791 new_visited = self .check_recursion_enforce (visited )
781- for component in self .components .values ():
782- component .check_recursion_rec (new_visited )
792+ for component_type in self .components .values ():
793+ if component_type is not self :
794+ component_type .check_recursion_rec (new_visited )
783795
784796
785797class Sequence_Sort (Parametric_Sort ):
@@ -1364,6 +1376,25 @@ def check_recursion_rec(self, visited):
13641376 self .record .check_recursion_rec (new_visited )
13651377
13661378
1379+ class Record_Null_Check (Expression ):
1380+ def __init__ (self , record ):
1381+ assert isinstance (record , Expression )
1382+ assert isinstance (record .sort , Record )
1383+ assert record .sort .is_recursive , "non-recursive records cannot be null"
1384+ super ().__init__ (BUILTIN_BOOLEAN )
1385+ self .record = record
1386+
1387+ def walk (self , visitor ):
1388+ assert isinstance (visitor , Visitor )
1389+ return visitor .visit_record_null_check (self ,
1390+ self .record .walk (visitor ))
1391+
1392+ def check_recursion_rec (self , visited ):
1393+ new_visited = self .check_recursion_enforce (visited )
1394+ self .sort .check_recursion_rec (new_visited )
1395+ self .record .check_recursion_rec (new_visited )
1396+
1397+
13671398class Function_Application (Expression ):
13681399 def __init__ (self , function , * arguments ):
13691400 assert isinstance (function , Function )
0 commit comments