mirror of
https://github.com/Z3Prover/z3
synced 2026-04-03 18:31:08 +00:00
Add Z3_mk_polymorphic_datatype to Python, .NET, Go, and TypeScript bindings (#9181)
* Add Z3_mk_polymorphic_datatype to Python, .NET, Go, and TypeScript bindings Agent-Logs-Url: https://github.com/Z3Prover/z3/sessions/13ef481d-61f5-47e1-8659-59cd91692fdd Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Improve Python error message for polymorphic datatype self-reference check Agent-Logs-Url: https://github.com/Z3Prover/z3/sessions/13ef481d-61f5-47e1-8659-59cd91692fdd Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
parent
56eeb5b52c
commit
56a8259717
5 changed files with 292 additions and 0 deletions
|
|
@ -1172,9 +1172,16 @@ export function createApi(Z3: Z3Core, em?: any): Z3HighLevel {
|
|||
createDatatypes(...datatypes: DatatypeImpl[]): DatatypeSortImpl[] {
|
||||
return createDatatypes(...datatypes);
|
||||
},
|
||||
createPolymorphicDatatype(typeParams: Sort<Name>[], datatype: DatatypeImpl): DatatypeSortImpl {
|
||||
return createPolymorphicDatatype(typeParams, datatype);
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
function TypeVariable(name: string): Sort<Name> {
|
||||
return new SortImpl(check(Z3.mk_type_variable(contextPtr, Z3.mk_string_symbol(contextPtr, name))));
|
||||
}
|
||||
|
||||
////////////////
|
||||
// Operations //
|
||||
////////////////
|
||||
|
|
@ -4689,6 +4696,10 @@ export function createApi(Z3: Z3Core, em?: any): Z3HighLevel {
|
|||
const datatypes = createDatatypes(this);
|
||||
return datatypes[0];
|
||||
}
|
||||
|
||||
createPolymorphic(typeParams: Sort<Name>[]): DatatypeSort<Name> {
|
||||
return createPolymorphicDatatype(typeParams, this);
|
||||
}
|
||||
}
|
||||
|
||||
class DatatypeSortImpl extends SortImpl implements DatatypeSort<Name> {
|
||||
|
|
@ -4845,6 +4856,84 @@ export function createApi(Z3: Z3Core, em?: any): Z3HighLevel {
|
|||
}
|
||||
}
|
||||
|
||||
function createPolymorphicDatatype(typeParams: Sort<Name>[], datatype: DatatypeImpl): DatatypeSortImpl {
|
||||
if (!(datatype instanceof DatatypeImpl)) {
|
||||
throw new Error('Datatype instance expected');
|
||||
}
|
||||
|
||||
const constructors: Z3_constructor[] = [];
|
||||
|
||||
try {
|
||||
for (const [constructorName, fields] of datatype.constructors) {
|
||||
const fieldNames: string[] = [];
|
||||
const fieldSorts: Z3_sort[] = [];
|
||||
const fieldRefs: number[] = [];
|
||||
|
||||
for (const [fieldName, fieldSort] of fields) {
|
||||
fieldNames.push(fieldName);
|
||||
|
||||
if (fieldSort instanceof DatatypeImpl) {
|
||||
// Self-recursive reference
|
||||
if (fieldSort !== datatype) {
|
||||
throw new Error(
|
||||
`Referenced datatype "${fieldSort.name}" is not the polymorphic datatype being created; mutual recursion is not supported in createPolymorphicDatatype`,
|
||||
);
|
||||
}
|
||||
fieldSorts.push(null as any);
|
||||
fieldRefs.push(0);
|
||||
} else {
|
||||
fieldSorts.push((fieldSort as Sort<Name>).ptr);
|
||||
fieldRefs.push(0);
|
||||
}
|
||||
}
|
||||
|
||||
const constructor = Z3.mk_constructor(
|
||||
contextPtr,
|
||||
Z3.mk_string_symbol(contextPtr, constructorName),
|
||||
Z3.mk_string_symbol(contextPtr, `is_${constructorName}`),
|
||||
fieldNames.map(name => Z3.mk_string_symbol(contextPtr, name)),
|
||||
fieldSorts,
|
||||
fieldRefs,
|
||||
);
|
||||
constructors.push(constructor);
|
||||
}
|
||||
|
||||
const nameSymbol = Z3.mk_string_symbol(contextPtr, datatype.name);
|
||||
const paramPtrs = typeParams.map(p => p.ptr);
|
||||
const resultSort = Z3.mk_polymorphic_datatype(contextPtr, nameSymbol, paramPtrs, constructors);
|
||||
|
||||
const sortImpl = new DatatypeSortImpl(resultSort);
|
||||
|
||||
// Attach constructor, recognizer, and accessor functions dynamically
|
||||
const numConstructors = sortImpl.numConstructors();
|
||||
for (let j = 0; j < numConstructors; j++) {
|
||||
const constructor = sortImpl.constructorDecl(j);
|
||||
const recognizer = sortImpl.recognizer(j);
|
||||
const constructorName = constructor.name().toString();
|
||||
|
||||
if (constructor.arity() === 0) {
|
||||
(sortImpl as any)[constructorName] = constructor.call();
|
||||
} else {
|
||||
(sortImpl as any)[constructorName] = constructor;
|
||||
}
|
||||
|
||||
(sortImpl as any)[`is_${constructorName}`] = recognizer;
|
||||
|
||||
for (let k = 0; k < constructor.arity(); k++) {
|
||||
const accessor = sortImpl.accessor(j, k);
|
||||
const accessorName = accessor.name().toString();
|
||||
(sortImpl as any)[accessorName] = accessor;
|
||||
}
|
||||
}
|
||||
|
||||
return sortImpl;
|
||||
} finally {
|
||||
for (const constructor of constructors) {
|
||||
Z3.del_constructor(contextPtr, constructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class QuantifierImpl<
|
||||
QVarSorts extends NonEmptySortArray<Name>,
|
||||
QSort extends BoolSort<Name> | SMTArraySort<Name, QVarSorts>,
|
||||
|
|
@ -5292,6 +5381,7 @@ export function createApi(Z3: Z3Core, em?: any): Z3HighLevel {
|
|||
Set,
|
||||
FiniteSet,
|
||||
Datatype,
|
||||
TypeVariable,
|
||||
|
||||
////////////////
|
||||
// Operations //
|
||||
|
|
|
|||
|
|
@ -479,6 +479,12 @@ export interface Context<Name extends string = 'main'> {
|
|||
/** @category Expressions */
|
||||
readonly Datatype: DatatypeCreation<Name>;
|
||||
|
||||
/**
|
||||
* Create a type variable sort for use as a parameter in polymorphic datatypes.
|
||||
* @category Sorts
|
||||
*/
|
||||
TypeVariable(name: string): Sort<Name>;
|
||||
|
||||
////////////////
|
||||
// Operations //
|
||||
////////////////
|
||||
|
|
@ -3136,6 +3142,15 @@ export interface Datatype<Name extends string = 'main'> {
|
|||
* For mutually recursive datatypes, use Context.createDatatypes instead.
|
||||
*/
|
||||
create(): DatatypeSort<Name>;
|
||||
|
||||
/**
|
||||
* Create a polymorphic datatype sort with explicit type parameters.
|
||||
* Type parameters should be sorts created with Context.TypeVariable.
|
||||
* Self-recursive fields may reference this Datatype object directly.
|
||||
*
|
||||
* @param typeParams Array of type variable sorts
|
||||
*/
|
||||
createPolymorphic(typeParams: AnySort<Name>[]): DatatypeSort<Name>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3154,6 +3169,17 @@ export interface DatatypeCreation<Name extends string> {
|
|||
* @returns Array of created DatatypeSort instances
|
||||
*/
|
||||
createDatatypes(...datatypes: Datatype<Name>[]): DatatypeSort<Name>[];
|
||||
|
||||
/**
|
||||
* Create a single polymorphic datatype sort with explicit type parameters.
|
||||
* Type parameters should be sorts created with Context.TypeVariable.
|
||||
* Self-recursive fields in constructors may reference the Datatype object directly.
|
||||
*
|
||||
* @param typeParams Array of type variable sorts
|
||||
* @param datatype Datatype declaration with constructors
|
||||
* @returns Created DatatypeSort instance
|
||||
*/
|
||||
createPolymorphicDatatype(typeParams: AnySort<Name>[], datatype: Datatype<Name>): DatatypeSort<Name>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue