@@ -17,6 +17,8 @@ import {
1717  Z3_ast_print_mode , 
1818  Z3_ast_vector , 
1919  Z3_context , 
20+   Z3_constructor , 
21+   Z3_constructor_list , 
2022  Z3_decl_kind , 
2123  Z3_error_code , 
2224  Z3_func_decl , 
@@ -88,6 +90,10 @@ import {
8890  FuncEntry , 
8991  SMTSetSort , 
9092  SMTSet , 
93+   Datatype , 
94+   DatatypeSort , 
95+   DatatypeExpr , 
96+   DatatypeCreation , 
9197}  from  './types' ; 
9298import  {  allSatisfy ,  assert ,  assertExhaustive  }  from  './utils' ; 
9399
@@ -825,6 +831,17 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
825831      } 
826832    } 
827833
834+     const  Datatype  =  Object . assign ( 
835+       ( name : string ) : DatatypeImpl  =>  { 
836+         return  new  DatatypeImpl ( ctx ,  name ) ; 
837+       } , 
838+       { 
839+         createDatatypes ( ...datatypes : DatatypeImpl [ ] ) : DatatypeSortImpl [ ]  { 
840+           return  createDatatypes ( ...datatypes ) ; 
841+         } 
842+       } 
843+     ) ; 
844+ 
828845    //////////////// 
829846    // Operations // 
830847    //////////////// 
@@ -2647,6 +2664,185 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
26472664      } 
26482665    } 
26492666
2667+     //////////////////////////// 
2668+     // Datatypes 
2669+     //////////////////////////// 
2670+ 
2671+     class  DatatypeImpl  implements  Datatype < Name >  { 
2672+       readonly  ctx : Context < Name > ; 
2673+       readonly  name : string ; 
2674+       public  constructors : Array < [ string ,  Array < [ string ,  Sort < Name >  |  Datatype < Name > ] > ] >  =  [ ] ; 
2675+ 
2676+       constructor ( ctx : Context < Name > ,  name : string )  { 
2677+         this . ctx  =  ctx ; 
2678+         this . name  =  name ; 
2679+       } 
2680+ 
2681+       declare ( name : string ,  ...fields : Array < [ string ,  Sort < Name >  |  Datatype < Name > ] > ) : this { 
2682+         this . constructors . push ( [ name ,  fields ] ) ; 
2683+         return  this ; 
2684+       } 
2685+ 
2686+       create ( ) : DatatypeSort < Name >  { 
2687+         const  datatypes  =  createDatatypes ( this ) ; 
2688+         return  datatypes [ 0 ] ; 
2689+       } 
2690+     } 
2691+ 
2692+     class  DatatypeSortImpl  extends  SortImpl  implements  DatatypeSort < Name >  { 
2693+       declare  readonly  __typename : DatatypeSort [ '__typename' ] ; 
2694+ 
2695+       numConstructors ( ) : number  { 
2696+         return  Z3 . get_datatype_sort_num_constructors ( contextPtr ,  this . ptr ) ; 
2697+       } 
2698+ 
2699+       constructorDecl ( idx : number ) : FuncDecl < Name >  { 
2700+         const  ptr  =  Z3 . get_datatype_sort_constructor ( contextPtr ,  this . ptr ,  idx ) ; 
2701+         return  new  FuncDeclImpl ( ptr ) ; 
2702+       } 
2703+ 
2704+       recognizer ( idx : number ) : FuncDecl < Name >  { 
2705+         const  ptr  =  Z3 . get_datatype_sort_recognizer ( contextPtr ,  this . ptr ,  idx ) ; 
2706+         return  new  FuncDeclImpl ( ptr ) ; 
2707+       } 
2708+ 
2709+       accessor( constructorIdx : number ,  accessorIdx : number ) : FuncDecl < Name >  { 
2710+         const  ptr  =  Z3 . get_datatype_sort_constructor_accessor ( contextPtr ,  this . ptr ,  constructorIdx ,  accessorIdx ) ; 
2711+         return  new  FuncDeclImpl ( ptr ) ; 
2712+       } 
2713+ 
2714+       cast ( other : CoercibleToExpr < Name > ) : DatatypeExpr < Name > ; 
2715+       cast ( other : DatatypeExpr < Name > ) : DatatypeExpr < Name > ; 
2716+       cast ( other : CoercibleToExpr < Name >  |  DatatypeExpr < Name > ) : DatatypeExpr < Name >  { 
2717+         if  ( isExpr ( other ) )  { 
2718+           assert ( this . eqIdentity ( other . sort ) ,  'Value cannot be converted to this datatype' ) ; 
2719+           return  other  as  DatatypeExpr < Name > ; 
2720+         } 
2721+         throw  new  Error ( 'Cannot coerce value to datatype expression' ) ; 
2722+       } 
2723+ 
2724+       subsort ( other : Sort < Name > )   { 
2725+         _assertContext ( other . ctx ) ; 
2726+         return  this . eqIdentity ( other ) ; 
2727+       } 
2728+     } 
2729+ 
2730+     class  DatatypeExprImpl  extends  ExprImpl < Z3_ast ,  DatatypeSortImpl >  implements  DatatypeExpr < Name >  { 
2731+       declare  readonly  __typename : DatatypeExpr [ '__typename' ] ; 
2732+     } 
2733+ 
2734+     function  createDatatypes ( ...datatypes : DatatypeImpl [ ] ) : DatatypeSortImpl [ ]  { 
2735+       if  ( datatypes . length  ===  0 )  { 
2736+         throw  new  Error ( 'At least one datatype must be provided' ) ; 
2737+       } 
2738+ 
2739+       // All datatypes must be from the same context 
2740+       const  dtCtx  =  datatypes [ 0 ] . ctx ; 
2741+       for  ( const  dt  of  datatypes )  { 
2742+         if  ( dt . ctx  !==  dtCtx )  { 
2743+           throw  new  Error ( 'All datatypes must be from the same context' ) ; 
2744+         } 
2745+       } 
2746+ 
2747+       const  sortNames  =  datatypes . map ( dt  =>  dt . name ) ; 
2748+       const  constructorLists : Z3_constructor_list [ ]  =  [ ] ; 
2749+       const  scopedConstructors : Z3_constructor [ ]  =  [ ] ; 
2750+ 
2751+       try  { 
2752+         // Create constructor lists for each datatype 
2753+         for  ( const  dt  of  datatypes )  { 
2754+           const  constructors : Z3_constructor [ ]  =  [ ] ; 
2755+ 
2756+           for  ( const  [ constructorName ,  fields ]  of  dt . constructors )  { 
2757+             const  fieldNames : string [ ]  =  [ ] ; 
2758+             const  fieldSorts : Z3_sort [ ]  =  [ ] ; 
2759+             const  fieldRefs : number [ ]  =  [ ] ; 
2760+ 
2761+             for  ( const  [ fieldName ,  fieldSort ]  of  fields )  { 
2762+               fieldNames . push ( fieldName ) ; 
2763+               
2764+               if  ( fieldSort  instanceof  DatatypeImpl )  { 
2765+                 // Reference to another datatype being defined 
2766+                 const  refIndex  =  datatypes . indexOf ( fieldSort ) ; 
2767+                 if  ( refIndex  ===  - 1 )  { 
2768+                   throw  new  Error ( `Referenced datatype "${ fieldSort . name }  " not found in datatypes being created` ) ; 
2769+                 } 
2770+                 // For recursive references, we pass null and the ref index 
2771+                 fieldSorts . push ( null  as  any ) ;  // null will be handled by the Z3 API 
2772+                 fieldRefs . push ( refIndex ) ; 
2773+               }  else  { 
2774+                 // Regular sort 
2775+                 fieldSorts . push ( ( fieldSort  as  Sort < Name > ) . ptr ) ; 
2776+                 fieldRefs . push ( 0 ) ; 
2777+               } 
2778+             } 
2779+ 
2780+             const  constructor  =  Z3 . mk_constructor ( 
2781+               contextPtr , 
2782+               Z3 . mk_string_symbol ( contextPtr ,  constructorName ) , 
2783+               Z3 . mk_string_symbol ( contextPtr ,  `is_${ constructorName }  ` ) , 
2784+               fieldNames . map ( name  =>  Z3 . mk_string_symbol ( contextPtr ,  name ) ) , 
2785+               fieldSorts , 
2786+               fieldRefs 
2787+             ) ; 
2788+             constructors . push ( constructor ) ; 
2789+             scopedConstructors . push ( constructor ) ; 
2790+           } 
2791+ 
2792+           const  constructorList  =  Z3 . mk_constructor_list ( contextPtr ,  constructors ) ; 
2793+           constructorLists . push ( constructorList ) ; 
2794+         } 
2795+ 
2796+         // Create the datatypes 
2797+         const  sortSymbols  =  sortNames . map ( name  =>  Z3 . mk_string_symbol ( contextPtr ,  name ) ) ; 
2798+         const  resultSorts  =  Z3 . mk_datatypes ( contextPtr ,  sortSymbols ,  constructorLists ) ; 
2799+ 
2800+         // Create DatatypeSortImpl instances 
2801+         const  results : DatatypeSortImpl [ ]  =  [ ] ; 
2802+         for  ( let  i  =  0 ;  i  <  resultSorts . length ;  i ++ )  { 
2803+           const  sortImpl  =  new  DatatypeSortImpl ( resultSorts [ i ] ) ; 
2804+           
2805+           // Attach constructor, recognizer, and accessor functions dynamically 
2806+           const  numConstructors  =  sortImpl . numConstructors ( ) ; 
2807+           for  ( let  j  =  0 ;  j  <  numConstructors ;  j ++ )  { 
2808+             const  constructor  =  sortImpl . constructorDecl ( j ) ; 
2809+             const  recognizer  =  sortImpl . recognizer ( j ) ; 
2810+             const  constructorName  =  constructor . name ( ) . toString ( ) ; 
2811+             
2812+             // Attach constructor function 
2813+             if  ( constructor . arity ( )  ===  0 )  { 
2814+               // Nullary constructor (constant) 
2815+               ( sortImpl  as  any ) [ constructorName ]  =  constructor . call ( ) ; 
2816+             }  else  { 
2817+               ( sortImpl  as  any ) [ constructorName ]  =  constructor ; 
2818+             } 
2819+             
2820+             // Attach recognizer function 
2821+             ( sortImpl  as  any ) [ `is_${ constructorName }  ` ]  =  recognizer ; 
2822+             
2823+             // Attach accessor functions 
2824+             for  ( let  k  =  0 ;  k  <  constructor . arity ( ) ;  k ++ )  { 
2825+               const  accessor  =  sortImpl . accessor ( j ,  k ) ; 
2826+               const  accessorName  =  accessor . name ( ) . toString ( ) ; 
2827+               ( sortImpl  as  any ) [ accessorName ]  =  accessor ; 
2828+             } 
2829+           } 
2830+           
2831+           results . push ( sortImpl ) ; 
2832+         } 
2833+ 
2834+         return  results ; 
2835+       }  finally  { 
2836+         // Clean up resources 
2837+         for  ( const  constructor  of  scopedConstructors )  { 
2838+           Z3 . del_constructor ( contextPtr ,  constructor ) ; 
2839+         } 
2840+         for  ( const  constructorList  of  constructorLists )  { 
2841+           Z3 . del_constructor_list ( contextPtr ,  constructorList ) ; 
2842+         } 
2843+       } 
2844+     } 
2845+ 
26502846    class  QuantifierImpl < 
26512847        QVarSorts  extends  NonEmptySortArray < Name > , 
26522848        QSort  extends  BoolSort < Name >  |  SMTArraySort < Name ,  QVarSorts > , 
@@ -3029,6 +3225,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
30293225      BitVec, 
30303226      Array, 
30313227      Set, 
3228+       Datatype, 
30323229
30333230      //////////////// 
30343231      // Operations // 
0 commit comments