Skip to content
This repository was archived by the owner on Apr 25, 2024. It is now read-only.

Commit bdba8da

Browse files
virgil-serbanutarv-auditortothtamas28
authored
Deduplicate productions (#505)
Co-authored-by: devops <[email protected]> Co-authored-by: Tamás Tóth <[email protected]>
1 parent e0cb467 commit bdba8da

File tree

7 files changed

+105
-13
lines changed

7 files changed

+105
-13
lines changed

package/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.344
1+
0.1.345

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
44

55
[tool.poetry]
66
name = "pyk"
7-
version = "0.1.344"
7+
version = "0.1.345"
88
description = ""
99
authors = [
1010
"Runtime Verification, Inc. <[email protected]>",

src/pyk/kast/kast.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def _freeze(m: Any) -> Any:
8888
if isinstance(m, (int, str, tuple, FrozenDict, frozenset)):
8989
return m
9090
elif isinstance(m, list):
91-
return tuple(v for v in m)
91+
return tuple(_freeze(v) for v in m)
9292
elif isinstance(m, dict):
9393
return FrozenDict((k, _freeze(v)) for (k, v) in m.items())
9494
raise ValueError(f"Don't know how to freeze attribute value {m} of type {type(m)}.")
@@ -133,6 +133,10 @@ def update(self, atts: Mapping[str, Any]) -> KAtt:
133133
def remove(self, atts: Iterable[str]) -> KAtt:
134134
return KAtt({k: v for k, v in self.atts.items() if k not in atts})
135135

136+
def drop_source(self) -> KAtt:
137+
new_atts = {key: value for key, value in self.atts.items() if key != self.SOURCE and key != self.LOCATION}
138+
return KAtt(atts=new_atts)
139+
136140
@property
137141
def pretty(self) -> str:
138142
if len(self) == 0:

src/pyk/kast/manip.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -493,15 +493,7 @@ def minimize_rule(rule: RL, keep_vars: Iterable[str] = ()) -> RL:
493493

494494

495495
def remove_source_map(definition: KDefinition) -> KDefinition:
496-
def _remove_source_map(att: KAtt) -> KAtt:
497-
atts = att.atts
498-
new_atts = {}
499-
for att_key in atts:
500-
if att_key != 'org.kframework.attributes.Source' and att_key != 'org.kframework.attributes.Location':
501-
new_atts[att_key] = atts[att_key]
502-
return KAtt(atts=new_atts)
503-
504-
return on_attributes(definition, _remove_source_map)
496+
return on_attributes(definition, lambda att: att.drop_source())
505497

506498

507499
def remove_attrs(term: KInner) -> KInner:

src/pyk/kast/outer.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,10 +1029,16 @@ def production_for_klabel(self, klabel: KLabel) -> KProduction:
10291029
prods = [prod for prod in self.productions if prod.klabel and prod.klabel.name == klabel.name]
10301030
_prods = [prod for prod in prods if 'unparseAvoid' not in prod.att]
10311031
if len(_prods) < len(prods):
1032-
prods = _prods
10331032
_LOGGER.warning(
10341033
f'Discarding {len(prods) - len(_prods)} productions with `unparseAvoid` attribute for label: {klabel}'
10351034
)
1035+
prods = _prods
1036+
# Automatically defined symbols like isInt may get multiple
1037+
# definitions in different modules.
1038+
_prods = list({prod.let_att(prod.att.drop_source()) for prod in prods})
1039+
if len(_prods) < len(prods):
1040+
_LOGGER.warning(f'Discarding {len(prods) - len(_prods)} equivalent productions')
1041+
prods = _prods
10361042
try:
10371043
self._production_for_klabel[klabel] = single(prods)
10381044
except ValueError as err:
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module MULTIPLE-DEFINITIONS
2+
imports A
3+
imports B
4+
imports BOOL
5+
6+
syntax KItem ::= a(KItem) [symbol, label(a)]
7+
| "b" [symbol, label(b)]
8+
| "c" [symbol, label(c)]
9+
rule a(X) => b requires isInt(X)
10+
rule a(X) => b requires notBool isInt(X)
11+
rule b => c
12+
endmodule
13+
14+
module A
15+
syntax Int
16+
endmodule
17+
18+
module B
19+
syntax Int
20+
endmodule
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING
4+
5+
import pytest
6+
7+
from pyk.cterm import CTerm
8+
from pyk.kast.inner import KApply, KSequence, KVariable
9+
from pyk.prelude.ml import mlTop
10+
from pyk.testing import KCFGExploreTest
11+
12+
from ..utils import K_FILES
13+
14+
if TYPE_CHECKING:
15+
from collections.abc import Iterable
16+
17+
from pyk.kcfg import KCFGExplore
18+
19+
20+
EXECUTE_TEST_DATA: Iterable[tuple[str]] = (('branch',),)
21+
22+
23+
class TestMultipleDefinitionsProof(KCFGExploreTest):
24+
KOMPILE_MAIN_FILE = K_FILES / 'multiple-definitions.k'
25+
26+
@staticmethod
27+
def config() -> CTerm:
28+
return CTerm(
29+
KApply(
30+
'<generatedTop>',
31+
KApply('<k>', KSequence(KApply('a', [KVariable('X')]))),
32+
KVariable('GENERATED_COUNTER_CELL'),
33+
),
34+
(mlTop(),),
35+
)
36+
37+
@pytest.mark.parametrize(
38+
'test_id',
39+
EXECUTE_TEST_DATA,
40+
ids=[test_id for test_id, *_ in EXECUTE_TEST_DATA],
41+
)
42+
def test_execute(
43+
self,
44+
kcfg_explore: KCFGExplore,
45+
test_id: str,
46+
) -> None:
47+
split_depth, split_post_term, split_next_terms, _logs = kcfg_explore.cterm_execute(self.config(), depth=1)
48+
49+
split_k = kcfg_explore.kprint.pretty_print(split_post_term.cell('K_CELL'))
50+
split_next_k = [kcfg_explore.kprint.pretty_print(split_post_term.cell('K_CELL')) for term in split_next_terms]
51+
52+
assert split_depth == 0
53+
assert len(split_next_terms) == 2
54+
assert 'a ( X:KItem )' == split_k
55+
assert [
56+
'a ( X:KItem )',
57+
'a ( X:KItem )',
58+
] == split_next_k
59+
60+
step_1_depth, step_1_post_term, step_1_next_terms, _logs = kcfg_explore.cterm_execute(
61+
split_next_terms[0], depth=1
62+
)
63+
step_1_k = kcfg_explore.kprint.pretty_print(step_1_post_term.cell('K_CELL'))
64+
assert 'c' == step_1_k
65+
66+
step_2_depth, step_2_post_term, step_2_next_terms, _logs = kcfg_explore.cterm_execute(
67+
split_next_terms[1], depth=1
68+
)
69+
step_2_k = kcfg_explore.kprint.pretty_print(step_1_post_term.cell('K_CELL'))
70+
assert 'c' == step_2_k

0 commit comments

Comments
 (0)