crosshair-tool 0.0.56__cp39-cp39-macosx_11_0_arm64.whl → 0.0.100__cp39-cp39-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- _crosshair_tracers.cpython-39-darwin.so +0 -0
- crosshair/__init__.py +1 -1
- crosshair/_mark_stacks.h +51 -24
- crosshair/_tracers.h +9 -5
- crosshair/_tracers_test.py +19 -9
- crosshair/auditwall.py +9 -8
- crosshair/auditwall_test.py +31 -19
- crosshair/codeconfig.py +3 -2
- crosshair/condition_parser.py +17 -133
- crosshair/condition_parser_test.py +54 -96
- crosshair/conftest.py +1 -1
- crosshair/copyext.py +91 -22
- crosshair/copyext_test.py +33 -0
- crosshair/core.py +259 -203
- crosshair/core_and_libs.py +20 -0
- crosshair/core_regestered_types_test.py +82 -0
- crosshair/core_test.py +693 -664
- crosshair/diff_behavior.py +76 -21
- crosshair/diff_behavior_test.py +132 -23
- crosshair/dynamic_typing.py +128 -18
- crosshair/dynamic_typing_test.py +91 -4
- crosshair/enforce.py +1 -6
- crosshair/enforce_test.py +15 -23
- crosshair/examples/check_examples_test.py +2 -1
- crosshair/fnutil.py +2 -3
- crosshair/fnutil_test.py +0 -7
- crosshair/fuzz_core_test.py +70 -83
- crosshair/libimpl/arraylib.py +10 -7
- crosshair/libimpl/binascii_ch_test.py +30 -0
- crosshair/libimpl/binascii_test.py +67 -0
- crosshair/libimpl/binasciilib.py +150 -0
- crosshair/libimpl/bisectlib_test.py +5 -5
- crosshair/libimpl/builtinslib.py +1002 -682
- crosshair/libimpl/builtinslib_ch_test.py +108 -30
- crosshair/libimpl/builtinslib_test.py +431 -143
- crosshair/libimpl/codecslib.py +22 -2
- crosshair/libimpl/codecslib_test.py +41 -9
- crosshair/libimpl/collectionslib.py +44 -8
- crosshair/libimpl/collectionslib_test.py +108 -20
- crosshair/libimpl/copylib.py +1 -1
- crosshair/libimpl/copylib_test.py +18 -0
- crosshair/libimpl/datetimelib.py +84 -67
- crosshair/libimpl/datetimelib_ch_test.py +12 -7
- crosshair/libimpl/datetimelib_test.py +5 -6
- crosshair/libimpl/decimallib.py +5257 -0
- crosshair/libimpl/decimallib_ch_test.py +78 -0
- crosshair/libimpl/decimallib_test.py +76 -0
- crosshair/libimpl/encodings/_encutil.py +21 -11
- crosshair/libimpl/fractionlib.py +16 -0
- crosshair/libimpl/fractionlib_test.py +80 -0
- crosshair/libimpl/functoolslib.py +19 -7
- crosshair/libimpl/functoolslib_test.py +22 -6
- crosshair/libimpl/hashliblib.py +30 -0
- crosshair/libimpl/hashliblib_test.py +18 -0
- crosshair/libimpl/heapqlib.py +32 -5
- crosshair/libimpl/heapqlib_test.py +15 -12
- crosshair/libimpl/iolib.py +7 -4
- crosshair/libimpl/ipaddresslib.py +8 -0
- crosshair/libimpl/itertoolslib_test.py +1 -1
- crosshair/libimpl/mathlib.py +165 -2
- crosshair/libimpl/mathlib_ch_test.py +44 -0
- crosshair/libimpl/mathlib_test.py +59 -16
- crosshair/libimpl/oslib.py +7 -0
- crosshair/libimpl/pathliblib_test.py +10 -0
- crosshair/libimpl/randomlib.py +1 -0
- crosshair/libimpl/randomlib_test.py +6 -4
- crosshair/libimpl/relib.py +180 -59
- crosshair/libimpl/relib_ch_test.py +26 -2
- crosshair/libimpl/relib_test.py +77 -14
- crosshair/libimpl/timelib.py +35 -13
- crosshair/libimpl/timelib_test.py +13 -3
- crosshair/libimpl/typeslib.py +15 -0
- crosshair/libimpl/typeslib_test.py +36 -0
- crosshair/libimpl/unicodedatalib_test.py +3 -3
- crosshair/libimpl/weakreflib.py +13 -0
- crosshair/libimpl/weakreflib_test.py +69 -0
- crosshair/libimpl/zliblib.py +15 -0
- crosshair/libimpl/zliblib_test.py +13 -0
- crosshair/lsp_server.py +21 -10
- crosshair/main.py +48 -28
- crosshair/main_test.py +59 -14
- crosshair/objectproxy.py +39 -14
- crosshair/objectproxy_test.py +27 -13
- crosshair/opcode_intercept.py +212 -24
- crosshair/opcode_intercept_test.py +172 -18
- crosshair/options.py +0 -1
- crosshair/patch_equivalence_test.py +5 -21
- crosshair/path_cover.py +7 -5
- crosshair/path_search.py +6 -4
- crosshair/path_search_test.py +1 -2
- crosshair/pathing_oracle.py +53 -10
- crosshair/pathing_oracle_test.py +21 -0
- crosshair/pure_importer_test.py +5 -21
- crosshair/register_contract.py +16 -6
- crosshair/register_contract_test.py +2 -14
- crosshair/simplestructs.py +154 -85
- crosshair/simplestructs_test.py +16 -2
- crosshair/smtlib.py +24 -0
- crosshair/smtlib_test.py +14 -0
- crosshair/statespace.py +319 -196
- crosshair/statespace_test.py +45 -0
- crosshair/stubs_parser.py +0 -2
- crosshair/test_util.py +87 -25
- crosshair/test_util_test.py +26 -0
- crosshair/tools/check_init_and_setup_coincide.py +0 -3
- crosshair/tools/generate_demo_table.py +2 -2
- crosshair/tracers.py +141 -49
- crosshair/type_repo.py +11 -4
- crosshair/unicode_categories.py +1 -0
- crosshair/util.py +158 -76
- crosshair/util_test.py +13 -20
- crosshair/watcher.py +4 -4
- crosshair/z3util.py +1 -1
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/METADATA +45 -36
- crosshair_tool-0.0.100.dist-info/RECORD +176 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/WHEEL +2 -1
- crosshair/examples/hypothesis/__init__.py +0 -2
- crosshair/examples/hypothesis/bugs_detected/simple_strategies.py +0 -74
- crosshair_tool-0.0.56.dist-info/RECORD +0 -152
- /crosshair/{examples/hypothesis/bugs_detected/__init__.py → py.typed} +0 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/entry_points.txt +0 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info/licenses}/LICENSE +0 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/top_level.txt +0 -0
crosshair/simplestructs.py
CHANGED
|
@@ -20,9 +20,15 @@ from typing import (
|
|
|
20
20
|
Union,
|
|
21
21
|
)
|
|
22
22
|
|
|
23
|
-
from crosshair.core import
|
|
24
|
-
from crosshair.tracers import NoTracing, tracing_iter
|
|
25
|
-
from crosshair.util import
|
|
23
|
+
from crosshair.core import deep_realize
|
|
24
|
+
from crosshair.tracers import NoTracing, ResumedTracing, tracing_iter
|
|
25
|
+
from crosshair.util import (
|
|
26
|
+
CrossHairValue,
|
|
27
|
+
assert_tracing,
|
|
28
|
+
is_hashable,
|
|
29
|
+
is_iterable,
|
|
30
|
+
name_of_type,
|
|
31
|
+
)
|
|
26
32
|
|
|
27
33
|
|
|
28
34
|
class MapBase(collections.abc.MutableMapping):
|
|
@@ -32,10 +38,10 @@ class MapBase(collections.abc.MutableMapping):
|
|
|
32
38
|
return NotImplemented
|
|
33
39
|
if len(self) != len(other):
|
|
34
40
|
return False
|
|
35
|
-
for
|
|
41
|
+
for k, self_value in self.items():
|
|
36
42
|
found = False
|
|
37
43
|
# We do a slow nested loop search because we don't want to hash the key.
|
|
38
|
-
for
|
|
44
|
+
for other_key, other_value in other.items():
|
|
39
45
|
if other_key != k:
|
|
40
46
|
continue
|
|
41
47
|
if self_value == other_value:
|
|
@@ -53,6 +59,16 @@ class MapBase(collections.abc.MutableMapping):
|
|
|
53
59
|
def __ch_pytype__(self):
|
|
54
60
|
return dict
|
|
55
61
|
|
|
62
|
+
def __ch_realize__(self):
|
|
63
|
+
memo = {}
|
|
64
|
+
return {deep_realize(k, memo): v for k, v in tracing_iter(self.items())}
|
|
65
|
+
|
|
66
|
+
def __ch_deep_realize__(self, memo):
|
|
67
|
+
return {
|
|
68
|
+
deep_realize(k, memo): deep_realize(v, memo)
|
|
69
|
+
for k, v in tracing_iter(self.items())
|
|
70
|
+
}
|
|
71
|
+
|
|
56
72
|
def __repr__(self):
|
|
57
73
|
contents = ", ".join(f"{repr(k)}: {repr(v)}" for (k, v) in self.items())
|
|
58
74
|
return "{" + contents + "}"
|
|
@@ -106,8 +122,10 @@ class SimpleDict(MapBase):
|
|
|
106
122
|
def __getitem__(self, key, default=_MISSING):
|
|
107
123
|
if not is_hashable(key):
|
|
108
124
|
raise TypeError("unhashable type")
|
|
109
|
-
for
|
|
110
|
-
|
|
125
|
+
for k, v in self.contents_:
|
|
126
|
+
# Note that the identity check below is not just an optimization;
|
|
127
|
+
# it is required to implement the semantics of NaN dict keys
|
|
128
|
+
if k is key or k == key:
|
|
111
129
|
return v
|
|
112
130
|
if default is _MISSING:
|
|
113
131
|
raise KeyError
|
|
@@ -116,7 +134,7 @@ class SimpleDict(MapBase):
|
|
|
116
134
|
def __setitem__(self, key, value):
|
|
117
135
|
if not is_hashable(key):
|
|
118
136
|
raise TypeError("unhashable type")
|
|
119
|
-
for
|
|
137
|
+
for i, (k, v) in enumerate(self.contents_):
|
|
120
138
|
if k == key:
|
|
121
139
|
self.contents_[i] = (k, value)
|
|
122
140
|
return
|
|
@@ -125,7 +143,7 @@ class SimpleDict(MapBase):
|
|
|
125
143
|
def __delitem__(self, key):
|
|
126
144
|
if not is_hashable(key):
|
|
127
145
|
raise TypeError("unhashable type")
|
|
128
|
-
for
|
|
146
|
+
for i, (k, v) in enumerate(self.contents_):
|
|
129
147
|
if k == key:
|
|
130
148
|
del self.contents_[i]
|
|
131
149
|
return
|
|
@@ -143,9 +161,6 @@ class SimpleDict(MapBase):
|
|
|
143
161
|
def __len__(self):
|
|
144
162
|
return self.contents_.__len__()
|
|
145
163
|
|
|
146
|
-
def items(self):
|
|
147
|
-
return self.contents_
|
|
148
|
-
|
|
149
164
|
def popitem(self):
|
|
150
165
|
if not self.contents_:
|
|
151
166
|
raise KeyError
|
|
@@ -478,9 +493,11 @@ class SequenceConcatenation(collections.abc.Sequence, SeqBase):
|
|
|
478
493
|
return second.__getitem__(
|
|
479
494
|
slice(
|
|
480
495
|
i.start - firstlen,
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
496
|
+
(
|
|
497
|
+
i.stop
|
|
498
|
+
if i.stop is None or i.stop < 0
|
|
499
|
+
else i.stop - firstlen
|
|
500
|
+
),
|
|
484
501
|
i.step,
|
|
485
502
|
)
|
|
486
503
|
)
|
|
@@ -728,14 +745,23 @@ class ShellMutableSequence(collections.abc.MutableSequence, SeqBase):
|
|
|
728
745
|
|
|
729
746
|
|
|
730
747
|
AbcSet = collections.abc.Set
|
|
748
|
+
AbcMutableSet = collections.abc.MutableSet
|
|
731
749
|
|
|
732
750
|
|
|
733
751
|
def _force_arg_to_set(x: object) -> AbcSet:
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
752
|
+
with NoTracing():
|
|
753
|
+
if isinstance(x, AbcSet):
|
|
754
|
+
while isinstance(x, ShellMutableSet):
|
|
755
|
+
x = x._inner
|
|
756
|
+
if isinstance(x, AbcMutableSet):
|
|
757
|
+
# Already known to have unique elements:
|
|
758
|
+
return LinearSet(list(tracing_iter(x)))
|
|
759
|
+
elif isinstance(x, (frozenset, FrozenSetBase)):
|
|
760
|
+
return x # Immutable set
|
|
761
|
+
if is_iterable(x):
|
|
762
|
+
with ResumedTracing():
|
|
763
|
+
return LinearSet.check_unique_and_create(x)
|
|
764
|
+
raise TypeError
|
|
739
765
|
|
|
740
766
|
|
|
741
767
|
class SetBase(CrossHairValue):
|
|
@@ -750,9 +776,6 @@ class SetBase(CrossHairValue):
|
|
|
750
776
|
def __repr__(self):
|
|
751
777
|
return deep_realize(self).__repr__()
|
|
752
778
|
|
|
753
|
-
def __hash__(self):
|
|
754
|
-
return hash(set(self))
|
|
755
|
-
|
|
756
779
|
def __and__(self, x):
|
|
757
780
|
if not isinstance(x, AbcSet):
|
|
758
781
|
return NotImplemented
|
|
@@ -813,7 +836,34 @@ class SetBase(CrossHairValue):
|
|
|
813
836
|
return self
|
|
814
837
|
|
|
815
838
|
|
|
816
|
-
class
|
|
839
|
+
class FrozenSetBase(SetBase, AbcSet):
|
|
840
|
+
def __ch_realize__(self):
|
|
841
|
+
# We are going to have to hash all of our contents,
|
|
842
|
+
# so just realize everything.
|
|
843
|
+
return self.__ch_deep_realize__({})
|
|
844
|
+
|
|
845
|
+
@assert_tracing(False)
|
|
846
|
+
def __ch_deep_realize__(self, memo):
|
|
847
|
+
contents = []
|
|
848
|
+
for item in tracing_iter(self):
|
|
849
|
+
contents.append(deep_realize(item, memo))
|
|
850
|
+
# TODO: This fails to preserve the iteration order;
|
|
851
|
+
# should we do something about that?:
|
|
852
|
+
return frozenset(contents)
|
|
853
|
+
|
|
854
|
+
def __ch_pytype__(self):
|
|
855
|
+
return frozenset
|
|
856
|
+
|
|
857
|
+
@classmethod
|
|
858
|
+
def _from_iterable(cls, it):
|
|
859
|
+
# overrides collections.abc.Set's version
|
|
860
|
+
return LinearSet.check_unique_and_create(it)
|
|
861
|
+
|
|
862
|
+
def __hash__(self):
|
|
863
|
+
return hash(deep_realize(self))
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
class SingletonSet(FrozenSetBase):
|
|
817
867
|
# Primarily this exists to avoid hashing values.
|
|
818
868
|
# TODO: should we fold uses of this into LinearSet, below?
|
|
819
869
|
|
|
@@ -830,9 +880,7 @@ class SingletonSet(SetBase, AbcSet):
|
|
|
830
880
|
return 1
|
|
831
881
|
|
|
832
882
|
|
|
833
|
-
class EmptySet(
|
|
834
|
-
# Primarily this exists to avoid hashing values.
|
|
835
|
-
|
|
883
|
+
class EmptySet(FrozenSetBase):
|
|
836
884
|
def __contains__(self, x):
|
|
837
885
|
if not is_hashable(x):
|
|
838
886
|
raise TypeError
|
|
@@ -846,7 +894,7 @@ class EmptySet(SetBase, AbcSet):
|
|
|
846
894
|
return 0
|
|
847
895
|
|
|
848
896
|
|
|
849
|
-
class LinearSet(
|
|
897
|
+
class LinearSet(FrozenSetBase):
|
|
850
898
|
# Primarily this exists to avoid hashing values.
|
|
851
899
|
# Presumes that its arguments are already unique.
|
|
852
900
|
|
|
@@ -881,7 +929,7 @@ class LinearSet(SetBase, AbcSet):
|
|
|
881
929
|
return len(self._items)
|
|
882
930
|
|
|
883
931
|
|
|
884
|
-
class LazySetCombination(
|
|
932
|
+
class LazySetCombination(FrozenSetBase):
|
|
885
933
|
"""
|
|
886
934
|
Provide a view over two sets and a logical operation in-between.
|
|
887
935
|
|
|
@@ -927,23 +975,29 @@ class LazySetCombination(SetBase, AbcSet):
|
|
|
927
975
|
return sum(1 for i in self.__iter__())
|
|
928
976
|
|
|
929
977
|
|
|
930
|
-
class ShellMutableSet(SetBase,
|
|
978
|
+
class ShellMutableSet(SetBase, AbcMutableSet):
|
|
931
979
|
"""
|
|
932
|
-
Provide a view over an immutable set.
|
|
980
|
+
Provide a mutable view over an immutable set.
|
|
933
981
|
|
|
934
|
-
The
|
|
982
|
+
The mutating operations simply replace the underlying
|
|
935
983
|
data structure entirely.
|
|
936
984
|
This set also attempts to preserve insertion order of the set,
|
|
937
985
|
assuming the underlying set(s) do so as well.
|
|
938
986
|
"""
|
|
939
987
|
|
|
940
|
-
_inner:
|
|
988
|
+
_inner: Union[frozenset, FrozenSetBase]
|
|
941
989
|
|
|
942
|
-
|
|
943
|
-
|
|
990
|
+
@assert_tracing(False)
|
|
991
|
+
def __init__(self, inner: Iterable = EmptySet()):
|
|
992
|
+
if isinstance(inner, FrozenSetBase):
|
|
944
993
|
self._inner = inner
|
|
994
|
+
elif isinstance(inner, frozenset):
|
|
995
|
+
self._inner = LinearSet(inner)
|
|
996
|
+
elif isinstance(inner, set):
|
|
997
|
+
self._inner = LinearSet(frozenset(inner))
|
|
945
998
|
elif is_iterable(inner):
|
|
946
|
-
|
|
999
|
+
with ResumedTracing():
|
|
1000
|
+
self._inner = LinearSet.check_unique_and_create(inner)
|
|
947
1001
|
else:
|
|
948
1002
|
raise TypeError
|
|
949
1003
|
|
|
@@ -989,7 +1043,7 @@ class ShellMutableSet(SetBase, collections.abc.MutableSet):
|
|
|
989
1043
|
# mutation operations
|
|
990
1044
|
def add(self, x):
|
|
991
1045
|
if not is_hashable(x):
|
|
992
|
-
raise TypeError("unhashable type")
|
|
1046
|
+
raise TypeError(f"unhashable type: '{name_of_type(type(x))}'")
|
|
993
1047
|
self.__ior__(SingletonSet(x))
|
|
994
1048
|
|
|
995
1049
|
def clear(self):
|
|
@@ -1000,7 +1054,7 @@ class ShellMutableSet(SetBase, collections.abc.MutableSet):
|
|
|
1000
1054
|
|
|
1001
1055
|
def discard(self, x):
|
|
1002
1056
|
if not is_hashable(x):
|
|
1003
|
-
raise TypeError("unhashable type")
|
|
1057
|
+
raise TypeError(f"unhashable type: '{name_of_type(type(x))}'")
|
|
1004
1058
|
self.__isub__(SingletonSet(x))
|
|
1005
1059
|
|
|
1006
1060
|
def intersection_update(self, x):
|
|
@@ -1023,74 +1077,89 @@ class ShellMutableSet(SetBase, collections.abc.MutableSet):
|
|
|
1023
1077
|
self._inner = self._inner.symmetric_difference(x)
|
|
1024
1078
|
|
|
1025
1079
|
def update(self, *iterables):
|
|
1026
|
-
|
|
1027
|
-
|
|
1080
|
+
for itr in iterables:
|
|
1081
|
+
additions = _force_arg_to_set(itr)
|
|
1082
|
+
self._inner = LazySetCombination(operator.or_, self._inner, additions)
|
|
1028
1083
|
|
|
1029
1084
|
def __or__(self, x):
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1085
|
+
with NoTracing():
|
|
1086
|
+
if not isinstance(x, AbcSet):
|
|
1087
|
+
return NotImplemented
|
|
1088
|
+
return ShellMutableSet(
|
|
1089
|
+
LazySetCombination(operator.or_, self._inner, _force_arg_to_set(x))
|
|
1090
|
+
)
|
|
1033
1091
|
|
|
1034
1092
|
__ror__ = __or__
|
|
1035
1093
|
|
|
1036
1094
|
def __and__(self, x):
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1095
|
+
with NoTracing():
|
|
1096
|
+
if not isinstance(x, AbcSet):
|
|
1097
|
+
return NotImplemented
|
|
1098
|
+
return ShellMutableSet(
|
|
1099
|
+
LazySetCombination(operator.and_, self._inner, _force_arg_to_set(x))
|
|
1100
|
+
)
|
|
1040
1101
|
|
|
1041
1102
|
__rand__ = __and__
|
|
1042
1103
|
|
|
1043
1104
|
def __xor__(self, x):
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1105
|
+
with NoTracing():
|
|
1106
|
+
if not isinstance(x, AbcSet):
|
|
1107
|
+
return NotImplemented
|
|
1108
|
+
return ShellMutableSet(
|
|
1109
|
+
LazySetCombination(operator.xor, self._inner, _force_arg_to_set(x))
|
|
1110
|
+
)
|
|
1047
1111
|
|
|
1048
1112
|
__rxor__ = __xor__
|
|
1049
1113
|
|
|
1050
1114
|
def __sub__(self, x):
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1115
|
+
with NoTracing():
|
|
1116
|
+
if not isinstance(x, AbcSet):
|
|
1117
|
+
return NotImplemented
|
|
1118
|
+
# TODO: why not lazy set combination here?
|
|
1119
|
+
return ShellMutableSet(
|
|
1120
|
+
LazySetCombination(lambda x, y: (x and not y), self._inner, x)
|
|
1121
|
+
)
|
|
1056
1122
|
|
|
1057
1123
|
def __rsub__(self, x):
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1124
|
+
with NoTracing():
|
|
1125
|
+
if not isinstance(x, AbcSet):
|
|
1126
|
+
return NotImplemented
|
|
1127
|
+
return ShellMutableSet(
|
|
1128
|
+
LazySetCombination(lambda x, y: (y and not x), self._inner, x)
|
|
1129
|
+
)
|
|
1063
1130
|
|
|
1064
1131
|
def __ior__(self, x):
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1132
|
+
with NoTracing():
|
|
1133
|
+
if not isinstance(x, AbcSet):
|
|
1134
|
+
return NotImplemented
|
|
1135
|
+
self._inner = LazySetCombination(
|
|
1136
|
+
operator.or_, self._inner, _force_arg_to_set(x)
|
|
1137
|
+
)
|
|
1138
|
+
return self
|
|
1069
1139
|
|
|
1070
1140
|
def __iand__(self, x):
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1141
|
+
with NoTracing():
|
|
1142
|
+
if not isinstance(x, AbcSet):
|
|
1143
|
+
return NotImplemented
|
|
1144
|
+
self._inner = LazySetCombination(
|
|
1145
|
+
operator.and_, self._inner, _force_arg_to_set(x)
|
|
1146
|
+
)
|
|
1147
|
+
return self
|
|
1075
1148
|
|
|
1076
1149
|
def __ixor__(self, x):
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1150
|
+
with NoTracing():
|
|
1151
|
+
if not isinstance(x, AbcSet):
|
|
1152
|
+
return NotImplemented
|
|
1153
|
+
self._inner = LazySetCombination(
|
|
1154
|
+
operator.xor, self._inner, _force_arg_to_set(x)
|
|
1155
|
+
)
|
|
1156
|
+
return self
|
|
1081
1157
|
|
|
1082
1158
|
def __isub__(self, x):
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
"""
|
|
1091
|
-
Test that slices of SequenceConcatenations are correct.
|
|
1092
|
-
|
|
1093
|
-
raises: IndexError
|
|
1094
|
-
post: _[0] == _[1]
|
|
1095
|
-
"""
|
|
1096
|
-
return (seq[i], (seq._first + seq._second)[i]) # type: ignore
|
|
1159
|
+
with NoTracing():
|
|
1160
|
+
if not isinstance(x, AbcSet):
|
|
1161
|
+
return NotImplemented
|
|
1162
|
+
self._inner = LazySetCombination(
|
|
1163
|
+
lambda x, y: (x and not y), self._inner, _force_arg_to_set(x)
|
|
1164
|
+
)
|
|
1165
|
+
return self
|
crosshair/simplestructs_test.py
CHANGED
|
@@ -3,7 +3,7 @@ import sys
|
|
|
3
3
|
|
|
4
4
|
import pytest
|
|
5
5
|
|
|
6
|
-
from crosshair.core import deep_realize
|
|
6
|
+
from crosshair.core import deep_realize, realize
|
|
7
7
|
from crosshair.simplestructs import (
|
|
8
8
|
LazySetCombination,
|
|
9
9
|
SequenceConcatenation,
|
|
@@ -87,6 +87,20 @@ def test_LazySetCombination_xor() -> None:
|
|
|
87
87
|
assert 5 in s
|
|
88
88
|
|
|
89
89
|
|
|
90
|
+
def test_ShellMutableDict_realize() -> None:
|
|
91
|
+
shell = ShellMutableMap({1: ShellMutableMap({2: 3})})
|
|
92
|
+
realized = realize(shell)
|
|
93
|
+
assert isinstance(realized, dict)
|
|
94
|
+
assert isinstance(realized[1], ShellMutableMap)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_ShellMutableDict_deep_realize() -> None:
|
|
98
|
+
shell = ShellMutableMap({1: ShellMutableMap({2: 3})})
|
|
99
|
+
realized = deep_realize(shell)
|
|
100
|
+
assert isinstance(realized, dict)
|
|
101
|
+
assert isinstance(realized[1], dict)
|
|
102
|
+
|
|
103
|
+
|
|
90
104
|
def test_ShellMutableSet_deepcopy() -> None:
|
|
91
105
|
ls = ["0", "1", "2", "3"]
|
|
92
106
|
shell = ShellMutableSet(ls)
|
|
@@ -223,7 +237,7 @@ def test_ShellMutableSet_errors() -> None:
|
|
|
223
237
|
with pytest.raises(KeyError):
|
|
224
238
|
ShellMutableSet([]).pop()
|
|
225
239
|
with pytest.raises(TypeError):
|
|
226
|
-
ShellMutableSet(4)
|
|
240
|
+
ShellMutableSet(4) # type: ignore
|
|
227
241
|
|
|
228
242
|
|
|
229
243
|
@pytest.mark.parametrize("start", [-3, -1, 0, 1, 3, None])
|
crosshair/smtlib.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import re
|
|
3
|
+
import struct
|
|
4
|
+
|
|
5
|
+
_SL2_PARSE_FLOAT_RE = re.compile(r"\(fp #(b\d+) #(b\d+) #(x.+)\)")
|
|
6
|
+
LITERAL_CONSTS = {
|
|
7
|
+
"(_ -zero 11 53)": -0.0,
|
|
8
|
+
"(_ +zero 11 53)": 0.0,
|
|
9
|
+
"(_ -oo 11 53)": -math.inf,
|
|
10
|
+
"(_ +oo 11 53)": math.inf,
|
|
11
|
+
"(_ NaN 11 53)": math.nan,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def parse_smtlib_literal(input: str):
|
|
16
|
+
literal_const = LITERAL_CONSTS.get(input, None)
|
|
17
|
+
if literal_const is not None:
|
|
18
|
+
return literal_const
|
|
19
|
+
match = _SL2_PARSE_FLOAT_RE.fullmatch(input)
|
|
20
|
+
if match:
|
|
21
|
+
sign, exp, significand = (int("0" + g, base=0) for g in match.groups())
|
|
22
|
+
return struct.unpack(
|
|
23
|
+
"d", struct.pack("Q", sign << 63 | exp << 52 | significand)
|
|
24
|
+
)[0]
|
crosshair/smtlib_test.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
import z3 # type: ignore
|
|
4
|
+
|
|
5
|
+
from crosshair.smtlib import parse_smtlib_literal
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_parse_smtlib_literal():
|
|
9
|
+
assert parse_smtlib_literal(z3.FPVal(1.23, z3.Float64).sexpr()) == 1.23
|
|
10
|
+
assert math.isnan(parse_smtlib_literal(z3.FPVal(math.nan, z3.Float64).sexpr()))
|
|
11
|
+
assert parse_smtlib_literal(z3.FPVal(-math.inf, z3.Float64).sexpr()) <= -math.inf
|
|
12
|
+
negzero = parse_smtlib_literal(z3.FPVal(-0.0, z3.Float64).sexpr())
|
|
13
|
+
assert negzero == 0
|
|
14
|
+
assert math.copysign(42, negzero) == -42
|