|
20 | 20 | from kevm_pyk.kevm import KEVM, KEVMNodePrinter, KEVMSemantics
|
21 | 21 | from kevm_pyk.utils import byte_offset_to_lines, legacy_explore, print_failure_info, print_model
|
22 | 22 | from pyk.cterm import CTerm
|
23 |
| -from pyk.kast.inner import KApply, KInner, KSort, KToken, KVariable |
24 |
| -from pyk.kast.manip import cell_label_to_var_name, collect, extract_lhs, flatten_label, minimize_term, top_down |
| 23 | +from pyk.kast.inner import KApply, KInner, KSequence, KSort, KToken, KVariable, Subst |
| 24 | +from pyk.kast.manip import ( |
| 25 | + cell_label_to_var_name, |
| 26 | + collect, |
| 27 | + extract_lhs, |
| 28 | + flatten_label, |
| 29 | + minimize_term, |
| 30 | + set_cell, |
| 31 | + top_down, |
| 32 | +) |
25 | 33 | from pyk.kast.outer import KDefinition, KFlatModule, KImport, KRequire
|
26 | 34 | from pyk.kcfg import KCFG
|
| 35 | +from pyk.kcfg.kcfg import Step |
27 | 36 | from pyk.kcfg.minimize import KCFGMinimizer
|
28 | 37 | from pyk.prelude.bytes import bytesToken
|
29 | 38 | from pyk.prelude.collections import map_empty
|
|
44 | 53 | _read_digest_file,
|
45 | 54 | append_to_file,
|
46 | 55 | empty_lemmas_file_contents,
|
| 56 | + ensure_name_is_unique, |
47 | 57 | foundry_toml_extra_contents,
|
48 | 58 | kontrol_file_contents,
|
49 | 59 | kontrol_toml_file_contents,
|
|
55 | 65 | from collections.abc import Iterable
|
56 | 66 | from typing import Any, Final
|
57 | 67 |
|
| 68 | + from pyk.cterm import CTermSymbolic |
58 | 69 | from pyk.kast.outer import KAst
|
59 | 70 | from pyk.kcfg.kcfg import NodeIdLike
|
| 71 | + from pyk.kcfg.semantics import KCFGExtendResult |
60 | 72 | from pyk.kcfg.tui import KCFGElem
|
61 | 73 | from pyk.proof.implies import RefutationProof
|
62 | 74 | from pyk.proof.show import NodePrinter
|
|
82 | 94 | _LOGGER: Final = logging.getLogger(__name__)
|
83 | 95 |
|
84 | 96 |
|
| 97 | +class KontrolSemantics(KEVMSemantics): |
| 98 | + |
| 99 | + @staticmethod |
| 100 | + def cut_point_rules( |
| 101 | + break_on_jumpi: bool, |
| 102 | + break_on_jump: bool, |
| 103 | + break_on_calls: bool, |
| 104 | + break_on_storage: bool, |
| 105 | + break_on_basic_blocks: bool, |
| 106 | + break_on_load_program: bool, |
| 107 | + ) -> list[str]: |
| 108 | + return ['FOUNDRY-CHEAT-CODES.rename'] + KEVMSemantics.cut_point_rules( |
| 109 | + break_on_jumpi, |
| 110 | + break_on_jump, |
| 111 | + break_on_calls, |
| 112 | + break_on_storage, |
| 113 | + break_on_basic_blocks, |
| 114 | + break_on_load_program, |
| 115 | + ) |
| 116 | + |
| 117 | + def _check_rename_pattern(self, cterm: CTerm) -> bool: |
| 118 | + """Given a CTerm, check if the rule 'FOUNDRY-CHEAT-CODES.rename' is at the top of the K_CELL. |
| 119 | +
|
| 120 | + :param cterm: The CTerm representing the current state of the proof node. |
| 121 | + :return: `True` if the pattern matches and a custom step can be made; `False` otherwise. |
| 122 | + """ |
| 123 | + abstract_pattern = KSequence( |
| 124 | + [ |
| 125 | + KApply('foundry_rename', [KVariable('###RENAME_TARGET'), KVariable('###NEW_NAME')]), |
| 126 | + KVariable('###CONTINUATION'), |
| 127 | + ] |
| 128 | + ) |
| 129 | + self._cached_subst = abstract_pattern.match(cterm.cell('K_CELL')) |
| 130 | + return self._cached_subst is not None |
| 131 | + |
| 132 | + def _exec_rename_custom_step(self, cterm: CTerm) -> KCFGExtendResult | None: |
| 133 | + subst = self._cached_subst |
| 134 | + assert subst is not None |
| 135 | + |
| 136 | + # Extract the target var and new name from the substitution |
| 137 | + target_var = subst['###RENAME_TARGET'] |
| 138 | + name_token = subst['###NEW_NAME'] |
| 139 | + assert type(target_var) is KVariable |
| 140 | + assert type(name_token) is KToken |
| 141 | + |
| 142 | + # Ensure the name is unique |
| 143 | + name_str = name_token.token[1:-1] |
| 144 | + if len(name_str) == 0: |
| 145 | + _LOGGER.warning('Name of symbolic variable cannot be empty. Reverting to the default name.') |
| 146 | + return None |
| 147 | + name = ensure_name_is_unique(name_str, cterm) |
| 148 | + |
| 149 | + # Replace var in configuration and constraints |
| 150 | + rename_subst = Subst({target_var.name: KVariable(name, target_var.sort)}) |
| 151 | + config = rename_subst(cterm.config) |
| 152 | + constraints = [rename_subst(constraint) for constraint in cterm.constraints] |
| 153 | + new_cterm = CTerm.from_kast(set_cell(config, 'K_CELL', KSequence(subst['###CONTINUATION']))) |
| 154 | + |
| 155 | + _LOGGER.info(f'Renaming {target_var.name} to {name}') |
| 156 | + return Step(CTerm(new_cterm.config, constraints), 1, (), ['foundry_rename'], cut=True) |
| 157 | + |
| 158 | + def custom_step(self, cterm: CTerm, _cterm_symbolic: CTermSymbolic) -> KCFGExtendResult | None: |
| 159 | + if self._check_rename_pattern(cterm): |
| 160 | + return self._exec_rename_custom_step(cterm) |
| 161 | + else: |
| 162 | + return super().custom_step(cterm, _cterm_symbolic) |
| 163 | + |
| 164 | + def can_make_custom_step(self, cterm: CTerm) -> bool: |
| 165 | + return self._check_rename_pattern(cterm) or super().can_make_custom_step(cterm) |
| 166 | + |
| 167 | + |
85 | 168 | class FoundryKEVM(KEVM):
|
86 | 169 | foundry: Foundry
|
87 | 170 |
|
@@ -841,7 +924,7 @@ def foundry_show(
|
841 | 924 | if options.failure_info:
|
842 | 925 | with legacy_explore(
|
843 | 926 | foundry.kevm,
|
844 |
| - kcfg_semantics=KEVMSemantics(), |
| 927 | + kcfg_semantics=KontrolSemantics(), |
845 | 928 | id=test_id,
|
846 | 929 | smt_timeout=options.smt_timeout,
|
847 | 930 | smt_retry_limit=options.smt_retry_limit,
|
@@ -908,7 +991,7 @@ def _collect_klabel(_k: KInner) -> None:
|
908 | 991 | ]
|
909 | 992 | sentences = [sent for sent in sentences if not _contains_foundry_klabel(sent.body)]
|
910 | 993 | sentences = [
|
911 |
| - sent for sent in sentences if not KEVMSemantics().is_terminal(CTerm.from_kast(extract_lhs(sent.body))) |
| 994 | + sent for sent in sentences if not KontrolSemantics().is_terminal(CTerm.from_kast(extract_lhs(sent.body))) |
912 | 995 | ]
|
913 | 996 | if len(sentences) == 0:
|
914 | 997 | _LOGGER.warning(f'No claims or rules retained for proof {proof.id}')
|
@@ -1098,7 +1181,7 @@ def foundry_simplify_node(
|
1098 | 1181 |
|
1099 | 1182 | with legacy_explore(
|
1100 | 1183 | foundry.kevm,
|
1101 |
| - kcfg_semantics=KEVMSemantics(), |
| 1184 | + kcfg_semantics=KontrolSemantics(), |
1102 | 1185 | id=apr_proof.id,
|
1103 | 1186 | bug_report=options.bug_report,
|
1104 | 1187 | kore_rpc_command=kore_rpc_command,
|
@@ -1146,7 +1229,7 @@ def check_cells_equal(cell: str, nodes: Iterable[KCFG.Node]) -> bool:
|
1146 | 1229 | check_cells_ne = [check_cell for check_cell in check_cells if not check_cells_equal(check_cell, nodes)]
|
1147 | 1230 |
|
1148 | 1231 | if check_cells_ne:
|
1149 |
| - if not all(KEVMSemantics().same_loop(nodes[0].cterm, nd.cterm) for nd in nodes): |
| 1232 | + if not all(KontrolSemantics().same_loop(nodes[0].cterm, nd.cterm) for nd in nodes): |
1150 | 1233 | raise ValueError(f'Nodes {options.nodes} cannot be merged because they differ in: {check_cells_ne}')
|
1151 | 1234 |
|
1152 | 1235 | anti_unification = nodes[0].cterm
|
@@ -1186,7 +1269,7 @@ def foundry_step_node(
|
1186 | 1269 |
|
1187 | 1270 | with legacy_explore(
|
1188 | 1271 | foundry.kevm,
|
1189 |
| - kcfg_semantics=KEVMSemantics(), |
| 1272 | + kcfg_semantics=KontrolSemantics(), |
1190 | 1273 | id=apr_proof.id,
|
1191 | 1274 | bug_report=options.bug_report,
|
1192 | 1275 | kore_rpc_command=kore_rpc_command,
|
@@ -1262,7 +1345,7 @@ def foundry_section_edge(
|
1262 | 1345 |
|
1263 | 1346 | with legacy_explore(
|
1264 | 1347 | foundry.kevm,
|
1265 |
| - kcfg_semantics=KEVMSemantics(), |
| 1348 | + kcfg_semantics=KontrolSemantics(), |
1266 | 1349 | id=apr_proof.id,
|
1267 | 1350 | bug_report=options.bug_report,
|
1268 | 1351 | kore_rpc_command=kore_rpc_command,
|
@@ -1313,7 +1396,7 @@ def foundry_get_model(
|
1313 | 1396 |
|
1314 | 1397 | with legacy_explore(
|
1315 | 1398 | foundry.kevm,
|
1316 |
| - kcfg_semantics=KEVMSemantics(), |
| 1399 | + kcfg_semantics=KontrolSemantics(), |
1317 | 1400 | id=proof.id,
|
1318 | 1401 | bug_report=options.bug_report,
|
1319 | 1402 | kore_rpc_command=kore_rpc_command,
|
|
0 commit comments