kdrag.theories.option
Algebraic data type for optional values
Functions
|
Helper to create Option None_ values >>> None_(smt.IntSort()) None_ |
|
Define an Option type for a given type T >>> OInt = Option(smt.IntSort()) >>> OInt.Some(1) Some(1) >>> OInt.None_ None_ >>> OInt.Some(1).val val(Some(1)) |
|
Helper to create Option values >>> Some(42) Some(42) >>> Some(42).sort() Option_Int |
|
Get the value of an Option, or a default value if it is None_ >>> get(Some(42), 0) If(is(Some, Some(42)), val(Some(42)), 0) |
|
Check if a value is an Option >>> is_option(Some(42)) True >>> is_option(42) False |
- kdrag.theories.option.None_(T: SortRef) DatatypeRef
Helper to create Option None_ values >>> None_(smt.IntSort()) None_
- Parameters:
T (SortRef)
- Return type:
DatatypeRef
- kdrag.theories.option.Option(T: SortRef) DatatypeSortRef
Define an Option type for a given type T >>> OInt = Option(smt.IntSort()) >>> OInt.Some(1) Some(1) >>> OInt.None_ None_ >>> OInt.Some(1).val val(Some(1))
- Parameters:
T (SortRef)
- Return type:
DatatypeSortRef
- kdrag.theories.option.Some(x: ExprRef) DatatypeRef
Helper to create Option values >>> Some(42) Some(42) >>> Some(42).sort() Option_Int
- Parameters:
x (ExprRef)
- Return type:
DatatypeRef
- kdrag.theories.option.get(x: DatatypeRef, default: ExprRef) ExprRef
Get the value of an Option, or a default value if it is None_ >>> get(Some(42), 0) If(is(Some, Some(42)), val(Some(42)), 0)
- Parameters:
x (DatatypeRef)
default (ExprRef)
- Return type:
ExprRef
- kdrag.theories.option.is_option(x: DatatypeRef) bool
Check if a value is an Option >>> is_option(Some(42)) True >>> is_option(42) False
- Parameters:
x (DatatypeRef)
- Return type:
bool
"""
Algebraic data type for optional values
"""
import functools
import kdrag.smt as smt
import kdrag as kd
@functools.cache
def Option(T: smt.SortRef) -> smt.DatatypeSortRef:
"""
Define an Option type for a given type T
>>> OInt = Option(smt.IntSort())
>>> OInt.Some(1)
Some(1)
>>> OInt.None_
None_
>>> OInt.Some(1).val
val(Some(1))
"""
Option = kd.Inductive("Option_" + T.name())
Option.declare("None_")
Option.declare("Some", ("val", T))
Option = Option.create()
return Option
def is_option(x: smt.DatatypeRef) -> bool:
"""
Check if a value is an Option
>>> is_option(Some(42))
True
>>> is_option(42)
False
"""
return smt._py2expr(x).sort().name().startswith("Option_")
# This should also perhaps be a SortDispatch
def get(x: smt.DatatypeRef, default: smt.ExprRef) -> smt.ExprRef:
"""
Get the value of an Option, or a default value if it is None_
>>> get(Some(42), 0)
If(is(Some, Some(42)), val(Some(42)), 0)
"""
default = smt._py2expr(default)
if not is_option(x):
raise ValueError(f"{x} is not an Option datatype. {x.sort()}")
elif x.val.sort() != default.sort():
raise ValueError(
f"default sort {default.sort()} does not match option sort {x.val.sort()}"
)
return smt.If(x.is_Some, x.val, default)
# I guess I could make this a SortDispatch for regularity. I just don't see why I'd need to overload in any way but the default
def Some(x: smt.ExprRef) -> smt.DatatypeRef:
"""
Helper to create Option values
>>> Some(42)
Some(42)
>>> Some(42).sort()
Option_Int
"""
x = smt._py2expr(x)
return Option(x.sort()).Some(x)
def None_(T: smt.SortRef) -> smt.DatatypeRef:
"""
Helper to create Option None_ values
>>> None_(smt.IntSort())
None_
"""
return Option(T).None_