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

Commit 9ba9da7

Browse files
author
François Guyot
committed
Merge branch 'master' into kcfg-key
2 parents b89539e + e3ef933 commit 9ba9da7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1109
-518
lines changed

.github/workflows/test-pr.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,28 @@ jobs:
5858
profile:
5959
needs: code-quality-checks
6060
name: 'Profiling'
61-
runs-on: ubuntu-latest
61+
runs-on: [self-hosted, linux, normal-ephemeral]
6262
steps:
6363
- name: 'Check out code'
6464
uses: actions/checkout@v3
65+
- name: 'Install Python'
66+
uses: actions/setup-python@v4
67+
with:
68+
python-version: '3.10'
6569
- name: 'Install Poetry'
6670
uses: Gr1N/setup-poetry@v8
71+
- name: 'Install K'
72+
run: |
73+
K_VERSION=$(cat deps/k_release)
74+
DEB_PACKAGE_NAME=kframework_${K_VERSION}_amd64_ubuntu_jammy.deb
75+
wget https://github.com/runtimeverification/k/releases/download/v${K_VERSION}/${DEB_PACKAGE_NAME}
76+
sudo apt-get update
77+
sudo apt-get -y install ./${DEB_PACKAGE_NAME}
78+
kompile --version
6779
- name: 'Run profiling'
6880
run: |
6981
make profile
70-
find /tmp/pytest-of-${USER}/pytest-current/ -type f | sort | xargs tail -n +1
82+
find /tmp/pytest-of-${USER}/pytest-current/ -type f -name '*.prof' | sort | xargs tail -n +1
7183
7284
integration-tests:
7385
needs: code-quality-checks

deps/k_release

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5.6.114
1+
5.6.125

package/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.320
1+
0.1.330

src/pyk/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
from typing import Final
77

88

9-
K_VERSION: Final = '5.6.114'
9+
K_VERSION: Final = '5.6.125'

src/pyk/__main__.py

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
from graphviz import Digraph
1010

11-
from .cli_utils import dir_path
11+
from .cli.args import KCLIArgs
12+
from .cli.utils import LOG_FORMAT, dir_path, loglevel
1213
from .coverage import get_rule_by_id, strip_coverage_logger
1314
from .cterm import split_config_and_constraints
1415
from .kast.inner import KInner
@@ -27,7 +28,6 @@
2728
from typing import Any, Final
2829

2930

30-
_LOG_FORMAT: Final = '%(levelname)s %(asctime)s %(name)s - %(message)s'
3131
_LOGGER: Final = logging.getLogger(__name__)
3232

3333

@@ -40,12 +40,7 @@ def main() -> None:
4040
cli_parser = create_argument_parser()
4141
args = cli_parser.parse_args()
4242

43-
if not args.verbose:
44-
logging.basicConfig(level=logging.WARNING, format=_LOG_FORMAT)
45-
elif args.verbose == 1:
46-
logging.basicConfig(level=logging.INFO, format=_LOG_FORMAT)
47-
elif args.verbose > 1:
48-
logging.basicConfig(level=logging.DEBUG, format=_LOG_FORMAT)
43+
logging.basicConfig(level=loglevel(args), format=LOG_FORMAT)
4944

5045
executor_name = 'exec_' + args.command.lower().replace('-', '_')
5146
if executor_name not in globals():
@@ -77,7 +72,7 @@ def exec_print(args: Namespace) -> None:
7772
minimized = minimize_term(disjunct, abstract_labels=abstract_labels, keep_cells=keep_cells)
7873
config, constraint = split_config_and_constraints(minimized)
7974
except ValueError as err:
80-
raise ValueError('The minified term does not contain a config cell.') from err
75+
raise ValueError('The minimized term does not contain a config cell.') from err
8176

8277
if not is_top(constraint):
8378
minimized_disjuncts.append(mlAnd([config, constraint], sort=GENERATED_TOP_CELL))
@@ -139,10 +134,7 @@ def exec_json_to_kore(args: dict[str, Any]) -> None:
139134

140135

141136
def create_argument_parser() -> ArgumentParser:
142-
logging_args = ArgumentParser(add_help=False)
143-
logging_args.add_argument(
144-
'-v', '--verbose', action='count', help='Verbosity level, repeat for more verbosity (up to two times).'
145-
)
137+
k_cli_args = KCLIArgs()
146138

147139
definition_args = ArgumentParser(add_help=False)
148140
definition_args.add_argument('definition_dir', type=dir_path, help='Path to definition directory.')
@@ -151,30 +143,21 @@ def create_argument_parser() -> ArgumentParser:
151143
pyk_args_command = pyk_args.add_subparsers(dest='command', required=True)
152144

153145
print_args = pyk_args_command.add_parser(
154-
'print', help='Pretty print a term.', parents=[logging_args, definition_args]
146+
'print',
147+
help='Pretty print a term.',
148+
parents=[k_cli_args.logging_args, definition_args, k_cli_args.display_args],
155149
)
156150
print_args.add_argument('term', type=FileType('r'), help='Input term (in JSON).')
157-
print_args.add_argument(
158-
'--minimize',
159-
dest='minimize',
160-
default=True,
161-
action='store_true',
162-
help='Minimize the JSON configuration before printing.',
163-
)
164-
print_args.add_argument(
165-
'--no-minimize',
166-
dest='minimize',
167-
action='store_false',
168-
help='Do not minimize the JSON configuration before printing.',
169-
)
170151
print_args.add_argument('--omit-labels', default='', nargs='?', help='List of labels to omit from output.')
171152
print_args.add_argument(
172153
'--keep-cells', default='', nargs='?', help='List of cells with primitive values to keep in output.'
173154
)
174155
print_args.add_argument('--output-file', type=FileType('w'), default='-')
175156

176157
prove_args = pyk_args_command.add_parser(
177-
'prove', help='Prove an input specification (using kprovex).', parents=[logging_args, definition_args]
158+
'prove',
159+
help='Prove an input specification (using kprovex).',
160+
parents=[k_cli_args.logging_args, definition_args],
178161
)
179162
prove_args.add_argument('main_file', type=str, help='Main file used for kompilation.')
180163
prove_args.add_argument('spec_file', type=str, help='File with the specification module.')
@@ -183,18 +166,22 @@ def create_argument_parser() -> ArgumentParser:
183166
prove_args.add_argument('kArgs', nargs='*', help='Arguments to pass through to K invocation.')
184167

185168
pyk_args_command.add_parser(
186-
'graph-imports', help='Graph the imports of a given definition.', parents=[logging_args, definition_args]
169+
'graph-imports',
170+
help='Graph the imports of a given definition.',
171+
parents=[k_cli_args.logging_args, definition_args],
187172
)
188173

189174
coverage_args = pyk_args_command.add_parser(
190-
'coverage', help='Convert coverage file to human readable log.', parents=[logging_args, definition_args]
175+
'coverage',
176+
help='Convert coverage file to human readable log.',
177+
parents=[k_cli_args.logging_args, definition_args],
191178
)
192179
coverage_args.add_argument('coverage_file', type=FileType('r'), help='Coverage file to build log for.')
193180
coverage_args.add_argument('-o', '--output', type=FileType('w'), default='-')
194181

195-
pyk_args_command.add_parser('kore-to-json', help='Convert textual KORE to JSON', parents=[logging_args])
182+
pyk_args_command.add_parser('kore-to-json', help='Convert textual KORE to JSON', parents=[k_cli_args.logging_args])
196183

197-
pyk_args_command.add_parser('json-to-kore', help='Convert JSON to textual KORE', parents=[logging_args])
184+
pyk_args_command.add_parser('json-to-kore', help='Convert JSON to textual KORE', parents=[k_cli_args.logging_args])
198185

199186
return pyk_args
200187

src/pyk/cli/args.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
from __future__ import annotations
2+
3+
from argparse import ArgumentParser
4+
from functools import cached_property
5+
from typing import TYPE_CHECKING
6+
7+
from ..utils import ensure_dir_path
8+
from .utils import dir_path, file_path
9+
10+
if TYPE_CHECKING:
11+
from typing import TypeVar
12+
13+
T = TypeVar('T')
14+
15+
16+
class KCLIArgs:
17+
@cached_property
18+
def logging_args(self) -> ArgumentParser:
19+
args = ArgumentParser(add_help=False)
20+
args.add_argument('--verbose', '-v', default=False, action='store_true', help='Verbose output.')
21+
args.add_argument('--debug', default=False, action='store_true', help='Debug output.')
22+
return args
23+
24+
@cached_property
25+
def parallel_args(self) -> ArgumentParser:
26+
args = ArgumentParser(add_help=False)
27+
args.add_argument('--workers', '-j', default=1, type=int, help='Number of processes to run in parallel.')
28+
return args
29+
30+
@cached_property
31+
def kompile_args(self) -> ArgumentParser:
32+
args = ArgumentParser(add_help=False)
33+
args.add_argument(
34+
'--emit-json',
35+
dest='emit_json',
36+
default=True,
37+
action='store_true',
38+
help='Emit JSON definition after compilation.',
39+
)
40+
args.add_argument(
41+
'--no-emit-json', dest='emit_json', action='store_false', help='Do not JSON definition after compilation.'
42+
)
43+
args.add_argument(
44+
'-ccopt',
45+
dest='ccopts',
46+
default=[],
47+
action='append',
48+
help='Additional arguments to pass to llvm-kompile.',
49+
)
50+
args.add_argument(
51+
'--no-llvm-kompile',
52+
dest='llvm_kompile',
53+
default=True,
54+
action='store_false',
55+
help='Do not run llvm-kompile process.',
56+
)
57+
args.add_argument(
58+
'--with-llvm-library',
59+
dest='llvm_library',
60+
default=False,
61+
action='store_true',
62+
help='Make kompile generate a dynamic llvm library.',
63+
)
64+
args.add_argument(
65+
'--enable-llvm-debug',
66+
dest='enable_llvm_debug',
67+
default=False,
68+
action='store_true',
69+
help='Make kompile generate debug symbols for llvm.',
70+
)
71+
args.add_argument(
72+
'--read-only-kompiled-directory',
73+
dest='read_only',
74+
default=False,
75+
action='store_true',
76+
help='Generated a kompiled directory that K will not attempt to write to afterwards.',
77+
)
78+
args.add_argument('-O0', dest='o0', default=False, action='store_true', help='Optimization level 0.')
79+
args.add_argument('-O1', dest='o1', default=False, action='store_true', help='Optimization level 1.')
80+
args.add_argument('-O2', dest='o2', default=False, action='store_true', help='Optimization level 2.')
81+
args.add_argument('-O3', dest='o3', default=False, action='store_true', help='Optimization level 3.')
82+
return args
83+
84+
@cached_property
85+
def display_args(self) -> ArgumentParser:
86+
args = ArgumentParser(add_help=False)
87+
args.add_argument('--minimize', dest='minimize', default=True, action='store_true', help='Minimize output.')
88+
args.add_argument('--no-minimize', dest='minimize', action='store_false', help='Do not minimize output.')
89+
return args
90+
91+
@cached_property
92+
def definition_args(self) -> ArgumentParser:
93+
args = ArgumentParser(add_help=False)
94+
args.add_argument(
95+
'-I', type=str, dest='includes', default=[], action='append', help='Directories to lookup K definitions in.'
96+
)
97+
args.add_argument('--main-module', default=None, type=str, help='Name of the main module.')
98+
args.add_argument('--syntax-module', default=None, type=str, help='Name of the syntax module.')
99+
args.add_argument('--spec-module', default=None, type=str, help='Name of the spec module.')
100+
args.add_argument('--definition', type=dir_path, dest='definition_dir', help='Path to definition to use.')
101+
args.add_argument(
102+
'--md-selector',
103+
type=str,
104+
help='Code selector expression to use when reading markdown.',
105+
)
106+
return args
107+
108+
@cached_property
109+
def spec_args(self) -> ArgumentParser:
110+
args = ArgumentParser(add_help=False)
111+
args.add_argument('spec_file', type=file_path, help='Path to spec file.')
112+
args.add_argument('--save-directory', type=ensure_dir_path, help='Path to where CFGs are stored.')
113+
args.add_argument(
114+
'--claim',
115+
type=str,
116+
dest='claim_labels',
117+
action='append',
118+
help='Only prove listed claims, MODULE_NAME.claim-id',
119+
)
120+
args.add_argument(
121+
'--exclude-claim',
122+
type=str,
123+
dest='exclude_claim_labels',
124+
action='append',
125+
help='Skip listed claims, MODULE_NAME.claim-id',
126+
)
127+
return args

src/pyk/cli/utils.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
from __future__ import annotations
2+
3+
import logging
4+
from pathlib import Path
5+
from typing import TYPE_CHECKING
6+
7+
from ..utils import check_dir_path, check_file_path, check_relative_path
8+
9+
if TYPE_CHECKING:
10+
from argparse import Namespace
11+
from collections.abc import Callable
12+
from typing import Final, TypeVar
13+
14+
from ..kcfg.kcfg import NodeIdLike
15+
16+
T1 = TypeVar('T1')
17+
T2 = TypeVar('T2')
18+
19+
LOG_FORMAT: Final = '%(levelname)s %(asctime)s %(name)s - %(message)s'
20+
21+
22+
def loglevel(args: Namespace) -> int:
23+
if args.debug:
24+
return logging.DEBUG
25+
26+
if args.verbose:
27+
return logging.INFO
28+
29+
return logging.WARNING
30+
31+
32+
def dir_path(s: str | Path) -> Path:
33+
path = Path(s)
34+
check_dir_path(path)
35+
return path
36+
37+
38+
def file_path(s: str) -> Path:
39+
path = Path(s)
40+
check_file_path(path)
41+
return path
42+
43+
44+
def relative_path(path: str | Path) -> Path:
45+
path = Path(path)
46+
check_relative_path(path)
47+
return path
48+
49+
50+
def list_of(elem_type: Callable[[str], T1], delim: str = ';') -> Callable[[str], list[T1]]:
51+
def parse(s: str) -> list[T1]:
52+
return [elem_type(elem) for elem in s.split(delim)]
53+
54+
return parse
55+
56+
57+
def node_id_like(s: str) -> NodeIdLike:
58+
try:
59+
return int(s)
60+
except ValueError:
61+
return s
62+
63+
64+
def arg_pair_of(
65+
fst_type: Callable[[str], T1], snd_type: Callable[[str], T2], delim: str = ','
66+
) -> Callable[[str], tuple[T1, T2]]:
67+
def parse(s: str) -> tuple[T1, T2]:
68+
elems = s.split(delim)
69+
length = len(elems)
70+
if length != 2:
71+
raise ValueError(f'Expected 2 elements, found {length}')
72+
73+
return fst_type(elems[0]), snd_type(elems[1])
74+
75+
return parse

0 commit comments

Comments
 (0)