Skip to content

Commit db2207b

Browse files
committed
CLI: add juliet commands
1 parent 59b6135 commit db2207b

File tree

5 files changed

+340
-184
lines changed

5 files changed

+340
-184
lines changed

chc/cmdline/AnalysisManager.py

Lines changed: 65 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import os
3434
import shutil
3535

36-
from typing import List, Optional, TYPE_CHECKING
36+
from typing import List, Optional, Tuple, TYPE_CHECKING
3737

3838
from chc.util.Config import Config
3939
import chc.util.fileutil as UF
@@ -55,7 +55,7 @@ def __init__(
5555
unreachability: bool = False,
5656
thirdpartysummaries: List[str] = [],
5757
nofilter: bool = True,
58-
verbose: bool = True,
58+
verbose: bool = False,
5959
) -> None:
6060
"""Initialize the analyzer location and target file location.
6161
@@ -90,7 +90,7 @@ def capp(self) -> "CApplication":
9090

9191
@property
9292
def contractpath(self) -> Optional[str]:
93-
return None
93+
return self.capp.contractpath
9494

9595
@property
9696
def config(self) -> Config:
@@ -112,51 +112,59 @@ def projectpath(self) -> str:
112112
def targetpath(self) -> str:
113113
return self.capp.targetpath
114114

115+
@property
116+
def projectname(self) -> str:
117+
return self.capp.projectname
118+
115119
def reset(self) -> None:
116120
"""Remove all file- and function-level files produced by the analysis."""
117121

118122
def remove(f: str) -> None:
119123
if os.path.isfile(f):
120124
os.remove(f)
121125

122-
def g(fi: "CFile") -> None:
123-
cfiledir = UF.get_cfile_directory(self.path, fi.name)
124-
if os.path.isdir(cfiledir):
125-
for f in os.listdir(cfiledir):
126-
if len(f) > 10 and (
127-
f[-8:-4] in ["_api", "_ppo", "_spo", "_pod"]
128-
or f[-9:-4] in ["_invs", "_vars"]
129-
):
130-
os.remove(os.path.join(cfiledir, f))
131-
remove(UF.get_cfile_predicate_dictionaryname(self.capp.path, fi.name))
132-
remove(UF.get_cfile_interface_dictionaryname(self.capp.path, fi.name))
133-
remove(UF.get_cfile_assignment_dictionaryname(self.capp.path, fi.name))
134-
remove(UF.get_cxreffile_filename(self.capp.path, fi.name))
135-
remove(UF.get_cfile_contexttablename(self.capp.path, fi.name))
136-
137-
self.capp.iter_files(g)
138-
remove(UF.get_global_definitions_filename(self.capp.path))
126+
for fi in self.capp.cfiles:
127+
for fn in fi.get_functions():
128+
fnargs: Tuple[str, str, Optional[str], str, str] = (
129+
fn.targetpath, fn.projectname, fn.cfilepath, fn.cfilename, fn.name)
130+
remove(UF.get_api_filename(*fnargs))
131+
remove(UF.get_ppo_filename(*fnargs))
132+
remove(UF.get_spo_filename(*fnargs))
133+
remove(UF.get_pod_filename(*fnargs))
134+
remove(UF.get_invs_filename(*fnargs))
135+
remove(UF.get_vars_filename(*fnargs))
136+
fiargs: Tuple[str, str, Optional[str], str] = (
137+
fi.targetpath, fi.projectname, fi.cfilepath, fi.cfilename)
138+
remove(UF.get_cfile_contexttablename(*fiargs))
139+
remove(UF.get_cfile_predicate_dictionaryname(*fiargs))
140+
remove(UF.get_cfile_interface_dictionaryname(*fiargs))
141+
remove(UF.get_cfile_assignment_dictionaryname(*fiargs))
142+
remove(UF.get_cxreffile_filename(*fiargs))
143+
144+
remove(UF.get_global_definitions_filename(
145+
self.capp.targetpath, self.capp.projectname))
139146

140147
def reset_logfiles(self) -> None:
141148
"""Remove all log files from semantics directory."""
142149

143-
def g(fi: "CFile") -> None:
144-
logfiledir = UF.get_cfile_logfiles_directory(self.path, fi.name)
145-
if os.path.isdir(logfiledir):
146-
for f in os.listdir(logfiledir):
147-
if (
148-
f.endswith("chlog")
149-
or f.endswith("infolog")
150-
or f.endswith("errorlog")
151-
):
152-
os.remove(os.path.join(logfiledir, f))
150+
def remove(f: str) -> None:
151+
if os.path.isfile(f):
152+
os.remove(f)
153153

154-
self.capp.iter_files(g)
154+
for fi in self.capp.cfiles:
155+
fiargs: Tuple[str, str, Optional[str], str] = (
156+
fi.targetpath, fi.projectname, fi.cfilepath, fi.cfilename)
157+
for kind in [
158+
"gencheck.chlog", "gencheck.infolog", "gencheck.errorlog",
159+
"primary.chlog", "primary.infolog", "primary.errorlog"]:
160+
fkargs = fiargs + (kind, )
161+
remove(UF.get_cfile_logfile_name(*fkargs))
155162

156-
def reset_tables(self, cfilename: str) -> None:
163+
def reset_tables(self, cfile: "CFile") -> None:
157164
"""Reload dictionaries from file (to get updated data from analyzer)."""
158165

159-
cfile = self.capp.get_file(cfilename)
166+
cfilename = cfile.name
167+
chklogger.logger.debug("Reset tables for %s", cfilename)
160168
cfile.reinitialize_tables()
161169
cfile.reload_ppos()
162170
cfile.reload_spos()
@@ -189,64 +197,30 @@ def _create_file_primary_proofobligations_cmd_partial(self) -> List[str]:
189197
cmd.append("-cfilename")
190198
return cmd
191199

192-
def rungui(self, name: str, outputpath: Optional[str] = None) -> None:
193-
semdir = os.path.dirname(self.path)
194-
analysisdir = os.path.dirname(semdir)
195-
if outputpath is None:
196-
outputpath = analysisdir
197-
if self.gui is None:
198-
print("Gui has not been configured.")
199-
exit(1)
200-
cmd: List[str] = [
201-
self.gui,
202-
"-summaries",
203-
self.chsummaries,
204-
"-output",
205-
outputpath,
206-
"-name",
207-
name,
208-
"-xpm",
209-
self.config.utildir,
210-
"-analysisdir",
211-
analysisdir,
212-
"-contractpath",
213-
self.contractpath,
214-
]
215-
print(cmd)
216-
try:
217-
result = subprocess.call(
218-
cmd,
219-
cwd=self.path,
220-
stdout=open(os.devnull, "w"),
221-
stderr=subprocess.STDOUT,
222-
)
223-
except subprocess.CalledProcessError as args:
224-
print(args.output)
225-
print(args)
226-
exit(1)
227-
228200
def create_file_primary_proofobligations(
229201
self, cfilename: str, cfilepath: Optional[str] = None) -> None:
230202
"""Call analyzer to create primary proof obligations for a single file."""
231203

204+
chklogger.logger.info(
205+
"Create primiary proof obligations for %s", cfilename)
232206
try:
233207
cmd = self._create_file_primary_proofobligations_cmd_partial()
234208
cmd.append(cfilename)
235209
if cfilepath is not None:
236210
cmd.extend(["-cfilepath", cfilepath])
211+
chklogger.logger.info(
212+
"Primary proof obligations are created for %s", cfilename)
213+
chklogger.logger.info(
214+
"Ocaml analyzer is called with %s", str(cmd))
237215
if self.verbose:
238-
chklogger.logger.info(
239-
"Primary proof obligations are created for %s", cfilename)
240-
chklogger.logger.info(
241-
"Ocaml analyzer is called with %s", str(cmd))
242216
result = subprocess.call(
243217
cmd, cwd=self.targetpath, stderr=subprocess.STDOUT)
244218
print("\nResult: " + str(result))
245219
# self.capp.get_file(cfilename).predicatedictionary.initialize()
246220
else:
247221
result = subprocess.call(
248222
cmd,
249-
cwd=self.path,
223+
cwd=self.targetpath,
250224
stdout=open(os.devnull, "w"),
251225
stderr=subprocess.STDOUT,
252226
)
@@ -267,18 +241,18 @@ def create_app_primary_proofobligations(self, processes: int = 1) -> None:
267241

268242
if processes > 1:
269243

270-
def f(cfile: str) -> None:
244+
def f(cfile: "CFile") -> None:
271245
cmd = self._create_file_primary_proofobligations_cmd_partial()
272-
cmd.append(cfile)
246+
cmd.append(cfile.name)
273247
self._execute_cmd(cmd)
274248

275-
self.capp.iter_filenames_parallel(f, processes)
249+
self.capp.iter_files_parallel(f, processes)
276250
else:
277251

278-
def f(cfile: str) -> None:
279-
self.create_file_primary_proofobligations(cfile)
252+
def f(cfile: "CFile") -> None:
253+
self.create_file_primary_proofobligations(cfile.name)
280254

281-
self.capp.iter_filenames(f)
255+
self.capp.iter_files(f)
282256

283257
def _generate_and_check_file_cmd_partial(self, domains: str) -> List[str]:
284258
cmd: List[str] = [
@@ -314,19 +288,17 @@ def generate_and_check_file(self, cfilename: str, domains: str) -> None:
314288
try:
315289
cmd = self._generate_and_check_file_cmd_partial(domains)
316290
cmd.append(cfilename)
291+
chklogger.logger.info(
292+
"Calling AI to generate invariants: %s",
293+
" ".join(cmd))
317294
if self.verbose:
318-
print(
319-
"Generating invariants and checking proof obligations for "
320-
+ cfilename
321-
)
322-
print(cmd)
323295
result = subprocess.call(
324296
cmd, cwd=self.targetpath, stderr=subprocess.STDOUT)
325297
print("\nResult: " + str(result))
326298
else:
327299
result = subprocess.call(
328300
cmd,
329-
cwd=self.path,
301+
cwd=self.targetpath,
330302
stdout=open(os.devnull, "w"),
331303
stderr=subprocess.STDOUT,
332304
)
@@ -343,19 +315,19 @@ def generate_and_check_app(self, domains: str, processes: int = 1) -> None:
343315

344316
if processes > 1:
345317

346-
def f(cfile: str) -> None:
318+
def f(cfile: "CFile") -> None:
347319
cmd = self._generate_and_check_file_cmd_partial(domains)
348-
cmd.append(cfile)
320+
cmd.append(cfile.name)
349321
self._execute_cmd(cmd)
350322

351-
self.capp.iter_filenames_parallel(f, processes)
323+
self.capp.iter_files_parallel(f, processes)
352324
else:
353325

354-
def f(cfile: str) -> None:
355-
self.generate_and_check_file(cfile, domains)
326+
def f(cfile: "CFile") -> None:
327+
self.generate_and_check_file(cfile.name, domains)
356328

357-
self.capp.iter_filenames(f)
358-
self.capp.iter_filenames(self.reset_tables)
329+
self.capp.iter_files(f)
330+
self.capp.iter_files(self.reset_tables)
359331

360332

361333
if __name__ == "__main__":

0 commit comments

Comments
 (0)