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

Commit c33340c

Browse files
Extract package konvert (#873)
Split module `konvert` into four modules: * `_kast_to_kore` * `_kore_to_kast` * `_module_to_kore` * `_utils` --------- Co-authored-by: devops <[email protected]>
1 parent e68db42 commit c33340c

File tree

8 files changed

+521
-509
lines changed

8 files changed

+521
-509
lines changed

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
project = 'pyk'
1010
author = 'Runtime Verification, Inc'
1111
copyright = '2024, Runtime Verification, Inc'
12-
version = '0.1.619'
13-
release = '0.1.619'
12+
version = '0.1.620'
13+
release = '0.1.620'
1414

1515
# -- General configuration ---------------------------------------------------
1616
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

package/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.619
1+
0.1.620

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.619"
7+
version = "0.1.620"
88
description = ""
99
authors = [
1010
"Runtime Verification, Inc. <[email protected]>",

src/pyk/konvert/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from ._kast_to_kore import _kast_to_kore, kast_to_kore, kflatmodule_to_kore, krule_to_kore
2+
from ._kore_to_kast import _kore_to_kast, kore_to_kast
3+
from ._module_to_kore import module_to_kore
4+
from ._utils import munge, unmunge

src/pyk/konvert/_kast_to_kore.py

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
from __future__ import annotations
2+
3+
import logging
4+
from functools import reduce
5+
from typing import TYPE_CHECKING
6+
7+
from ..cterm import CTerm
8+
from ..kast.inner import KApply, KSequence, KSort, KToken, KVariable
9+
from ..kast.manip import bool_to_ml_pred, extract_lhs, extract_rhs
10+
from ..kast.outer import KRule
11+
from ..kore.prelude import DOTK, SORT_K
12+
from ..kore.syntax import DV, And, App, Axiom, EVar, Import, MLPattern, MLQuant, Module, Rewrites, SortApp, String, Top
13+
from ..prelude.bytes import BYTES, pretty_bytes_str
14+
from ..prelude.k import K
15+
from ..prelude.string import STRING, pretty_string
16+
from ._utils import munge
17+
18+
if TYPE_CHECKING:
19+
from typing import Final
20+
21+
from ..kast import KInner
22+
from ..kast.outer import KDefinition, KFlatModule, KImport
23+
from ..kore.kompiled import KompiledKore
24+
from ..kore.syntax import Pattern, Sentence, Sort
25+
26+
_LOGGER: Final = logging.getLogger(__name__)
27+
28+
29+
ML_CONN_LABELS: Final = {
30+
'#Top': r'\top',
31+
'#Bottom': r'\bottom',
32+
'#Not': r'\not',
33+
'#And': r'\and',
34+
'#Or': r'\or',
35+
'#Implies': r'\implies',
36+
'#Iff': r'\iff',
37+
}
38+
39+
ML_QUANT_LABELS: Final = {
40+
'#Exists': r'\exists',
41+
'#Forall': r'\forall',
42+
}
43+
44+
ML_PRED_LABELS: Final = {
45+
'#Ceil': r'\ceil',
46+
'#Floor': r'\floor',
47+
'#Equals': r'\equals',
48+
'#In': r'\in',
49+
}
50+
51+
ML_PATTERN_LABELS: Final = dict(
52+
**ML_CONN_LABELS,
53+
**ML_QUANT_LABELS,
54+
**ML_PRED_LABELS,
55+
)
56+
57+
58+
def kast_to_kore(
59+
kast_defn: KDefinition,
60+
kompiled_kore: KompiledKore,
61+
kast: KInner,
62+
sort: KSort | None = None,
63+
) -> Pattern:
64+
if sort is None:
65+
sort = K
66+
kast = kast_defn.add_ksequence_under_k_productions(kast)
67+
kast = kast_defn.sort_vars(kast, sort)
68+
kast = kast_defn.add_cell_map_items(kast)
69+
kast = kast_defn.add_sort_params(kast)
70+
kore = _kast_to_kore(kast)
71+
kore = kompiled_kore.add_injections(kore, _ksort_to_kore(sort))
72+
return kore
73+
74+
75+
# 'krule' should have sorts on variables
76+
def krule_to_kore(kast_defn: KDefinition, kompiled_kore: KompiledKore, krule: KRule) -> Axiom:
77+
krule_body = krule.body
78+
krule_lhs = CTerm(extract_lhs(krule_body), [bool_to_ml_pred(krule.requires)])
79+
krule_rhs = CTerm(extract_rhs(krule_body), [bool_to_ml_pred(krule.ensures)])
80+
81+
top_level_kore_sort = SortApp('SortGeneratedTopCell')
82+
top_level_k_sort = KSort('GeneratedTopCell')
83+
# The backend does not like rewrite rules without a precondition
84+
if len(krule_lhs.constraints) > 0:
85+
kore_lhs0: Pattern = kast_to_kore(kast_defn, kompiled_kore, krule_lhs.kast, sort=top_level_k_sort)
86+
else:
87+
kore_lhs0 = And(
88+
top_level_kore_sort,
89+
(
90+
kast_to_kore(kast_defn, kompiled_kore, krule_lhs.kast, sort=top_level_k_sort),
91+
Top(top_level_kore_sort),
92+
),
93+
)
94+
95+
kore_rhs0: Pattern = kast_to_kore(kast_defn, kompiled_kore, krule_rhs.kast, sort=top_level_k_sort)
96+
97+
kore_lhs = kompiled_kore.add_injections(kore_lhs0, sort=top_level_kore_sort)
98+
kore_rhs = kompiled_kore.add_injections(kore_rhs0, sort=top_level_kore_sort)
99+
prio = krule.priority
100+
attrs = [App(symbol='priority', sorts=(), args=(String(str(prio)),))]
101+
if 'label' in krule.att:
102+
label = krule.att['label']
103+
attrs.append(App(symbol='label', sorts=(), args=(String(label),)))
104+
axiom = Axiom(
105+
vars=(),
106+
pattern=Rewrites(
107+
sort=top_level_kore_sort,
108+
left=kore_lhs,
109+
right=kore_rhs,
110+
),
111+
attrs=attrs,
112+
)
113+
return axiom
114+
115+
116+
def kflatmodule_to_kore(kast_defn: KDefinition, kompiled_kore: KompiledKore, kflatmodule: KFlatModule) -> Module:
117+
kore_axioms: list[Sentence] = []
118+
for sent in kflatmodule.sentences:
119+
if type(sent) is not KRule:
120+
raise ValueError(f'Cannot convert sentence to Kore: {sent}')
121+
kore_axioms.append(krule_to_kore(kast_defn, kompiled_kore, sent))
122+
imports: list[Sentence] = [_kimport_to_kore(kimport) for kimport in kflatmodule.imports]
123+
return Module(name=kflatmodule.name, sentences=(imports + kore_axioms))
124+
125+
126+
def _kimport_to_kore(kimport: KImport) -> Import:
127+
return Import(module_name=kimport.name, attrs=())
128+
129+
130+
def _ksort_to_kore(ksort: KSort) -> SortApp:
131+
return SortApp('Sort' + ksort.name)
132+
133+
134+
def _kast_to_kore(term: KInner) -> Pattern:
135+
stack: list = [term, []]
136+
while True:
137+
patterns = stack[-1]
138+
term = stack[-2]
139+
idx = len(patterns) - len(term.terms)
140+
if not idx:
141+
stack.pop()
142+
stack.pop()
143+
pattern = _kinner_to_kore(term, patterns)
144+
if not stack:
145+
return pattern
146+
stack[-1].append(pattern)
147+
else:
148+
stack.append(term.terms[idx])
149+
stack.append([])
150+
151+
152+
def _kinner_to_kore(kinner: KInner, patterns: list[Pattern]) -> Pattern:
153+
match kinner:
154+
case KToken():
155+
assert not patterns
156+
return _ktoken_to_kore(kinner)
157+
case KVariable():
158+
assert not patterns
159+
return _kvariable_to_kore(kinner)
160+
case KSequence():
161+
return _ksequence_to_kore(kinner, patterns)
162+
case KApply():
163+
return _kapply_to_kore(kinner, patterns)
164+
case _:
165+
raise ValueError(f'Unsupported KInner: {kinner}')
166+
167+
168+
def _ktoken_to_kore(ktoken: KToken) -> DV:
169+
value: String
170+
if ktoken.sort == STRING:
171+
value = String(pretty_string(ktoken))
172+
elif ktoken.sort == BYTES:
173+
value = String(pretty_bytes_str(ktoken))
174+
else:
175+
value = String(ktoken.token)
176+
177+
sort = _ksort_to_kore(ktoken.sort)
178+
179+
return DV(sort, value)
180+
181+
182+
def _kvariable_to_kore(kvar: KVariable) -> EVar:
183+
sort: Sort
184+
if kvar.sort:
185+
sort = _ksort_to_kore(kvar.sort)
186+
else:
187+
sort = SORT_K
188+
return EVar('Var' + munge(kvar.name), sort)
189+
190+
191+
def _ksequence_to_kore(kseq: KSequence, patterns: list[Pattern]) -> Pattern:
192+
if not patterns:
193+
return DOTK
194+
195+
unit: Pattern
196+
args: list[Pattern]
197+
198+
last = patterns[-1]
199+
if type(last) is EVar and last.sort == SORT_K:
200+
unit = last
201+
args = patterns[:-1]
202+
else:
203+
unit = DOTK
204+
args = patterns
205+
206+
args.reverse()
207+
return reduce(lambda x, y: App('kseq', (), (y, x)), args, unit)
208+
209+
210+
def _kapply_to_kore(kapply: KApply, patterns: list[Pattern]) -> Pattern:
211+
if kapply.label.name in ML_QUANT_LABELS:
212+
return _kapply_to_ml_quant(kapply, patterns)
213+
214+
return _kapply_to_pattern(kapply, patterns)
215+
216+
217+
def _kapply_to_ml_quant(kapply: KApply, patterns: list[Pattern]) -> MLQuant:
218+
label = kapply.label
219+
symbol = ML_QUANT_LABELS[label.name]
220+
sorts = tuple(_ksort_to_kore(ksort) for ksort in label.params)
221+
return MLQuant.of(symbol, sorts, patterns)
222+
223+
224+
def _kapply_to_pattern(kapply: KApply, patterns: list[Pattern]) -> Pattern:
225+
label = kapply.label
226+
symbol = _label_to_kore(label.name)
227+
sorts = tuple(_ksort_to_kore(ksort) for ksort in label.params)
228+
229+
if label.name in ML_PATTERN_LABELS:
230+
return MLPattern.of(symbol, sorts, patterns)
231+
232+
return App(symbol, sorts, patterns)
233+
234+
235+
def _label_to_kore(label: str) -> str:
236+
if label in ML_PATTERN_LABELS:
237+
return ML_PATTERN_LABELS[label]
238+
239+
return 'Lbl' + munge(label)

0 commit comments

Comments
 (0)