Skip to content

Commit acf0d60

Browse files
committed
Merge remote-tracking branch 'origin/master' into docker-tweaks
2 parents b54946b + e322c01 commit acf0d60

11 files changed

Lines changed: 182 additions & 3 deletions

File tree

kmir/pyproject.toml

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

55
[project]
66
name = "kmir"
7-
version = "0.3.129"
7+
version = "0.3.130"
88
description = ""
99
requires-python = "~=3.10"
1010
dependencies = [

kmir/src/kmir/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from typing import Final
22

3-
VERSION: Final = '0.3.129'
3+
VERSION: Final = '0.3.130'

kmir/src/kmir/rust/cargo.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
from __future__ import annotations
22

33
import json
4+
import logging
45
import subprocess
56
from functools import cached_property
67
from pathlib import Path
8+
from typing import TYPE_CHECKING
9+
10+
from pyk.utils import run_process_2
11+
12+
if TYPE_CHECKING:
13+
from typing import Any, Final
14+
15+
_LOGGER: Final = logging.getLogger(__name__)
16+
_LOG_FORMAT: Final = '%(levelname)s %(asctime)s %(name)s - %(message)s'
17+
18+
SMIR_JSON_DIR: Final = Path(__file__).parents[4] / 'deps/stable-mir-json/'
719

820

921
class CargoProject:
@@ -80,3 +92,13 @@ def default_target(self) -> str:
8092
)
8193

8294
return bin_targets[0]
95+
96+
97+
def cargo_get_smir_json(rs_file: Path) -> dict[str, Any]:
98+
smir_json_result = SMIR_JSON_DIR / rs_file.with_suffix('.smir.json').name
99+
run_process_2(['cargo', 'run', '--', '-Zno-codegen', str(rs_file)], cwd=SMIR_JSON_DIR)
100+
json_smir = json.loads(smir_json_result.read_text())
101+
_LOGGER.info(f'Loaded: {smir_json_result}')
102+
smir_json_result.unlink()
103+
_LOGGER.info(f'Deleted: {smir_json_result}')
104+
return json_smir
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
fn add(x: i32, y: i32) -> i32 {
2+
x + y
3+
}
4+
5+
fn sub(x: i32, y: i32) -> i32 {
6+
x - y
7+
}
8+
9+
fn mul(x: i32, y: i32) -> i32 {
10+
x * y
11+
}
12+
13+
fn div(x: i32, y: i32) -> i32 {
14+
x / y
15+
}
16+
17+
fn main() {
18+
assert!(add(3, 4) == 7);
19+
20+
// assert!(sub(3, 4) == -1); // FAILING
21+
22+
assert!(mul(3, 4) == 12);
23+
24+
// assert!(div(12, 4) == 3); // FAILING
25+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
assert!(false)
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
assert!(true)
3+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
fn cmp_lt(x: i32, y: i32) -> bool {
2+
x < y
3+
}
4+
5+
fn cmp_le(x: i32, y: i32) -> bool {
6+
x <= y
7+
}
8+
9+
fn cmp_gt(x: i32, y: i32) -> bool {
10+
x > y
11+
}
12+
13+
fn cmp_ge(x: i32, y: i32) -> bool {
14+
x >= y
15+
}
16+
17+
fn cmp_eq(x: i32, y: i32) -> bool {
18+
x == y
19+
}
20+
21+
fn cmp_neq(x: i32, y: i32) -> bool {
22+
x != y
23+
}
24+
25+
fn main() {
26+
assert!( cmp_lt(3, 4));
27+
assert!(!cmp_lt(4, 3));
28+
assert!(!cmp_lt(4, 4));
29+
30+
assert!( cmp_le(3, 4));
31+
assert!(!cmp_le(4, 3));
32+
assert!( cmp_le(4, 4));
33+
34+
assert!(!cmp_gt(3, 4));
35+
assert!( cmp_gt(4, 3));
36+
assert!(!cmp_gt(4, 4));
37+
38+
assert!(!cmp_ge(3, 4));
39+
assert!( cmp_ge(4, 3));
40+
assert!( cmp_ge(4, 4));
41+
42+
assert!(!cmp_eq(4, 3));
43+
assert!( cmp_eq(4, 4));
44+
45+
assert!( cmp_neq(4, 3));
46+
assert!(!cmp_neq(4, 4));
47+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fn ite(flag: bool) {
2+
if flag {
3+
assert!(false)
4+
} else {
5+
assert!(true)
6+
}
7+
}
8+
9+
fn main() {
10+
ite(false)
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fn ite(flag: bool) {
2+
if flag {
3+
assert!(true)
4+
} else {
5+
assert!(false)
6+
}
7+
}
8+
9+
fn main() {
10+
ite(true)
11+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from __future__ import annotations
2+
3+
from pathlib import Path
4+
from typing import TYPE_CHECKING
5+
6+
import pytest
7+
from pyk.cterm import CTerm
8+
from pyk.kast.inner import KInner, Subst
9+
from pyk.kast.manip import split_config_from
10+
from pyk.kcfg import KCFG
11+
from pyk.proof.reachability import APRProof, APRProver
12+
13+
from kmir.kmir import KMIR
14+
from kmir.parse.parser import Parser
15+
from kmir.rust.cargo import cargo_get_smir_json
16+
17+
if TYPE_CHECKING:
18+
from kmir.tools import Tools
19+
20+
21+
PROVING_DIR = (Path(__file__).parent / 'data' / 'prove-rs').resolve(strict=True)
22+
PROVING_FILES = list(PROVING_DIR.glob('*.rs'))
23+
24+
25+
@pytest.mark.parametrize(
26+
'rs_file',
27+
PROVING_FILES,
28+
ids=[spec.stem for spec in PROVING_FILES],
29+
)
30+
def test_prove_rs(rs_file: Path, tmp_path: Path, kmir: KMIR, tools: Tools) -> None:
31+
should_fail = rs_file.stem.endswith('fail')
32+
smir_json = cargo_get_smir_json(rs_file)
33+
34+
parser = Parser(kmir.definition)
35+
parse_result = parser.parse_mir_json(smir_json, 'Pgm')
36+
assert parse_result is not None
37+
kmir_kast, _ = parse_result
38+
assert isinstance(kmir_kast, KInner)
39+
40+
config = tools.make_init_config(kmir_kast, 'main')
41+
config_with_cell_vars, _ = split_config_from(config)
42+
43+
lhs = CTerm(config)
44+
45+
rhs_subst = Subst({'K_CELL': KMIR.Symbols.END_PROGRAM})
46+
rhs = CTerm(rhs_subst(config_with_cell_vars))
47+
kcfg = KCFG()
48+
init_node = kcfg.create_node(lhs)
49+
target_node = kcfg.create_node(rhs)
50+
apr_proof = APRProof('PROOF', kcfg, [], init_node.id, target_node.id, {})
51+
with kmir.kcfg_explore('PROOF-TEST') as kcfg_explore:
52+
prover = APRProver(kcfg_explore)
53+
prover.advance_proof(apr_proof)
54+
if not should_fail:
55+
assert apr_proof.passed
56+
else:
57+
assert apr_proof.failed

0 commit comments

Comments
 (0)