Revision 6bc919cb
Added by Guillaume Davy almost 10 years ago
gen_contracts.py | ||
---|---|---|
1 |
import sys |
|
2 |
import os |
|
3 |
import re |
|
4 |
import tempfile |
|
5 |
import subprocess |
|
6 |
import shutil |
|
7 |
|
|
8 |
import xml.etree.ElementTree as ET |
|
9 |
|
|
10 |
re_property_old = re.compile('--%[ ]*PROPERTY([^;]*);') |
|
11 |
re_property = re.compile('--![ ]*PROPERTY[ ]*:([^;]*);') |
|
12 |
re_node = re.compile('.*node.*') |
|
13 |
re_ensures = re.compile('.*ensures.*') |
|
14 |
re_k = re.compile('--![ ]*k[ ]*:([^;]*);') |
|
15 |
re_frama_res = re.compile('Proved goals:[ ]*([0-9]*)[ ]*/[ ]*([0-9]*)') |
|
16 |
|
|
17 |
def findInLines(lines, regex): |
|
18 |
res = [] |
|
19 |
for i in range(len(lines)): |
|
20 |
m = regex.search(lines[i]) |
|
21 |
if m: |
|
22 |
res.append((i, m.groups()[0] if len(m.groups()) > 0 else None)) |
|
23 |
return res |
|
24 |
|
|
25 |
def modProperties(lines, temp): |
|
26 |
properties_old = findInLines(lines, re_property_old) |
|
27 |
|
|
28 |
if not properties_old: |
|
29 |
return (None, "NO_OLD", None) |
|
30 |
|
|
31 |
for (i, data) in properties_old: |
|
32 |
lines[i] = "--!PROPERTY:{};\n".format(data) |
|
33 |
return (lines, "OK", None) |
|
34 |
|
|
35 |
def addEnsures(lines, temp): |
|
36 |
nodes = findInLines(lines, re_node) |
|
37 |
ensures = findInLines(lines, re_ensures) |
|
38 |
properties = findInLines(lines, re_property) |
|
39 |
if not nodes: |
|
40 |
return (None, "NONODE", None) |
|
41 |
if ensures: |
|
42 |
return (None, "ALREADY", None) |
|
43 |
if not properties: |
|
44 |
return (None, "NOPR", None) |
|
45 |
if len(properties) > 1: |
|
46 |
return (None, "TOOMUCHPR", None) |
|
47 |
for (i, data) in properties: |
|
48 |
bestd = len(lines) |
|
49 |
best = -1 |
|
50 |
for (j, _) in nodes: |
|
51 |
if i - j < bestd: |
|
52 |
bestd = i - j |
|
53 |
best = j |
|
54 |
lines.insert(best, "--@ensures " + data + ";\n") |
|
55 |
return (lines, "OK", None) |
|
56 |
|
|
57 |
TIMEOUT=1 |
|
58 |
MAX=10 |
|
59 |
def addK(lines, temp): |
|
60 |
properties = findInLines(lines, re_property) |
|
61 |
k = findInLines(lines, re_k) |
|
62 |
if k: |
|
63 |
return (None, "ALREADY", "KEEP") |
|
64 |
if not properties: |
|
65 |
return (None, "NOPR", None) |
|
66 |
if len(properties) > 1: |
|
67 |
return (None, "TOOMUCHPR", None) |
|
68 |
top = temp + "/no_k.lus" |
|
69 |
f = open(top, 'w') |
|
70 |
f.write("".join(lines)) |
|
71 |
f.close() |
|
72 |
p = subprocess.Popen(["timeout", "10", "pkind", top, "-timeout", str(TIMEOUT), "-k_incremental", str(MAX)], stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
73 |
(stdout, stderr) = p.communicate() |
|
74 |
try: |
|
75 |
root = ET.fromstring(stdout) |
|
76 |
except ET.ParseError: |
|
77 |
return (None, "TIMEOUT", None) |
|
78 |
answer = root.find(".//Answer") |
|
79 |
if answer is None: |
|
80 |
return (None, "NO_ANS", None) |
|
81 |
if answer.text != "valid": |
|
82 |
return (None, "INVALID", None) |
|
83 |
k = root.find(".//K") |
|
84 |
if k is None: |
|
85 |
return (None, "NO_K", None) |
|
86 |
try: |
|
87 |
k = int(k.text) |
|
88 |
except ValueError: |
|
89 |
return (None, "NOTPROVED", None) |
|
90 |
lines.insert(properties[0][0], "--!k:{};\n".format(k)) |
|
91 |
return (lines, "OK("+"k=" + str(k)+")", "KEEP") |
|
92 |
|
|
93 |
def compileLustre(lines, temp): |
|
94 |
top = temp + "/top.lus" |
|
95 |
f = open(top, 'w') |
|
96 |
f.write("".join(lines)) |
|
97 |
f.close() |
|
98 |
p = subprocess.Popen(["lustrec", "-d", temp ,"-acsl-proof", top], stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
99 |
(stdout, stderr) = p.communicate() |
|
100 |
res = p.wait() |
|
101 |
if res != 0: |
|
102 |
return (None, "ERR_"+str(res), None) |
|
103 |
return (lines, "OK", None) |
|
104 |
|
|
105 |
def framac(lines, temp): |
|
106 |
FRAMAC=["frama-c", temp+"/top.c"] |
|
107 |
p = subprocess.Popen(FRAMAC, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
108 |
(stdout, stderr) = p.communicate() |
|
109 |
res = p.wait() |
|
110 |
if res != 0: |
|
111 |
return (None, "PARSE_"+str(res), None) |
|
112 |
FRAMAC=["frama-c", "-wp", "-wp-prover", "CVC4,alt-ergo,z3,coq", temp+"/top.c", "-wp-par", "2", "-wp-model", "ref", """-wp-tactic="Require Why3. intros. hnf. repeat split;try why3 \"CVC3\" timelimit 10;try why3 \"Z3\" timelimit 10;why3 \"CVC4\" timelimit 10" """, "-wp-script", temp+"/top.coq", "-wp-no-let"] |
|
113 |
#"-wp-rte", |
|
114 |
p = subprocess.Popen(FRAMAC, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
115 |
(stdout, stderr) = p.communicate() |
|
116 |
res = p.wait() |
|
117 |
if res != 0: |
|
118 |
return (None, "ERR_"+str(res), None) |
|
119 |
m = re_frama_res.search(stdout) |
|
120 |
if not m: |
|
121 |
return (None, "BAD_OUT", None) |
|
122 |
return (lines, str(m.group(1))+"/"+str(m.group(2)), None) |
|
123 |
|
|
124 |
|
|
125 |
def parseFile(inp, todo): |
|
126 |
lines = inp.readlines() |
|
127 |
|
|
128 |
temp = tempfile.mkdtemp(prefix="contracts_") |
|
129 |
res = "" |
|
130 |
data = None |
|
131 |
ok = False |
|
132 |
for f in todo: |
|
133 |
x = [[]] |
|
134 |
(newlines, r, cmd) = f(lines[:], temp) |
|
135 |
res += "{:8} ".format(r[:8]) |
|
136 |
if newlines: |
|
137 |
lines = newlines |
|
138 |
if cmd == "STOP": |
|
139 |
break |
|
140 |
if cmd == "KEEP": |
|
141 |
ok = True |
|
142 |
if ok: |
|
143 |
res += "WRITE" |
|
144 |
data = "".join(lines) |
|
145 |
shutil.rmtree(temp) |
|
146 |
|
|
147 |
return (res, data) |
|
148 |
|
|
149 |
TODO=[modProperties, addEnsures, addK, compileLustre, framac] |
|
150 |
|
|
151 |
LENGTH=40 |
|
152 |
|
|
153 |
target="./generated/" |
|
154 |
|
|
155 |
#if os.path.exists(target): |
|
156 |
# shutil.rmtree(target) |
|
157 |
|
|
158 |
orig = "./tests/" |
|
159 |
for root, dirs, files in os.walk(orig): |
|
160 |
short = root[len(orig):] |
|
161 |
os.mkdir(target+"/"+short) |
|
162 |
for x in files: |
|
163 |
if not x.endswith(".lus"): |
|
164 |
continue |
|
165 |
inp = open(root+"/"+x, "r") |
|
166 |
(res, data) = parseFile(inp, TODO) |
|
167 |
inp.close() |
|
168 |
if data: |
|
169 |
out = open(target+"/"+short+"/"+x, "w") |
|
170 |
out.write(data) |
|
171 |
out.close() |
|
172 |
print(("Process {0:"+str(LENGTH)+"} : {1}").format(("./"+short+"/"+x)[:LENGTH], res)) |
|
173 |
sys.stdout.flush() |
tests/gen_contracts.py | ||
---|---|---|
1 |
import sys |
|
2 |
import os |
|
3 |
import re |
|
4 |
import tempfile |
|
5 |
import subprocess |
|
6 |
import shutil |
|
7 |
|
|
8 |
import xml.etree.ElementTree as ET |
|
9 |
|
|
10 |
re_property_old = re.compile('--%[ ]*PROPERTY([^;]*);') |
|
11 |
re_property = re.compile('--![ ]*PROPERTY[ ]*:([^;]*);') |
|
12 |
re_node = re.compile('.*node.*') |
|
13 |
re_ensures = re.compile('.*ensures.*') |
|
14 |
re_k = re.compile('--![ ]*k[ ]*:([^;]*);') |
|
15 |
re_frama_res = re.compile('Proved goals:[ ]*([0-9]*)[ ]*/[ ]*([0-9]*)') |
|
16 |
|
|
17 |
def findInLines(lines, regex): |
|
18 |
res = [] |
|
19 |
for i in range(len(lines)): |
|
20 |
m = regex.search(lines[i]) |
|
21 |
if m: |
|
22 |
res.append((i, m.groups()[0] if len(m.groups()) > 0 else None)) |
|
23 |
return res |
|
24 |
|
|
25 |
def modProperties(lines, temp): |
|
26 |
properties_old = findInLines(lines, re_property_old) |
|
27 |
|
|
28 |
if not properties_old: |
|
29 |
return (None, "NO_OLD", None) |
|
30 |
|
|
31 |
for (i, data) in properties_old: |
|
32 |
lines[i] = "--!PROPERTY:{};\n".format(data) |
|
33 |
return (lines, "OK", None) |
|
34 |
|
|
35 |
def addEnsures(lines, temp): |
|
36 |
nodes = findInLines(lines, re_node) |
|
37 |
ensures = findInLines(lines, re_ensures) |
|
38 |
properties = findInLines(lines, re_property) |
|
39 |
if not nodes: |
|
40 |
return (None, "NONODE", None) |
|
41 |
if ensures: |
|
42 |
return (None, "ALREADY", None) |
|
43 |
if not properties: |
|
44 |
return (None, "NOPR", None) |
|
45 |
if len(properties) > 1: |
|
46 |
return (None, "TOOMUCHPR", None) |
|
47 |
for (i, data) in properties: |
|
48 |
bestd = len(lines) |
|
49 |
best = -1 |
|
50 |
for (j, _) in nodes: |
|
51 |
if i - j < bestd: |
|
52 |
bestd = i - j |
|
53 |
best = j |
|
54 |
lines.insert(best, "--@ensures " + data + ";\n") |
|
55 |
return (lines, "OK", None) |
|
56 |
|
|
57 |
TIMEOUT=1 |
|
58 |
MAX=10 |
|
59 |
def addK(lines, temp): |
|
60 |
properties = findInLines(lines, re_property) |
|
61 |
k = findInLines(lines, re_k) |
|
62 |
if k: |
|
63 |
return (None, "ALREADY", "KEEP") |
|
64 |
if not properties: |
|
65 |
return (None, "NOPR", None) |
|
66 |
if len(properties) > 1: |
|
67 |
return (None, "TOOMUCHPR", None) |
|
68 |
top = temp + "/no_k.lus" |
|
69 |
f = open(top, 'w') |
|
70 |
f.write("".join(lines)) |
|
71 |
f.close() |
|
72 |
p = subprocess.Popen(["timeout", "10", "pkind", top, "-timeout", str(TIMEOUT), "-k_incremental", str(MAX)], stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
73 |
(stdout, stderr) = p.communicate() |
|
74 |
try: |
|
75 |
root = ET.fromstring(stdout) |
|
76 |
except ET.ParseError: |
|
77 |
return (None, "TIMEOUT", None) |
|
78 |
answer = root.find(".//Answer") |
|
79 |
if answer is None: |
|
80 |
return (None, "NO_ANS", None) |
|
81 |
if answer.text != "valid": |
|
82 |
return (None, "INVALID", None) |
|
83 |
k = root.find(".//K") |
|
84 |
if k is None: |
|
85 |
return (None, "NO_K", None) |
|
86 |
try: |
|
87 |
k = int(k.text) |
|
88 |
except ValueError: |
|
89 |
return (None, "NOTPROVED", None) |
|
90 |
lines.insert(properties[0][0], "--!k:{};\n".format(k)) |
|
91 |
return (lines, "OK("+"k=" + str(k)+")", "KEEP") |
|
92 |
|
|
93 |
def compileLustre(lines, temp): |
|
94 |
top = temp + "/top.lus" |
|
95 |
f = open(top, 'w') |
|
96 |
f.write("".join(lines)) |
|
97 |
f.close() |
|
98 |
p = subprocess.Popen(["lustrec", "-d", temp ,"-acsl-proof", top], stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
99 |
(stdout, stderr) = p.communicate() |
|
100 |
res = p.wait() |
|
101 |
if res != 0: |
|
102 |
return (None, "ERR_"+str(res), None) |
|
103 |
return (lines, "OK", None) |
|
104 |
|
|
105 |
def framac(lines, temp): |
|
106 |
FRAMAC=["frama-c", temp+"/top.c"] |
|
107 |
p = subprocess.Popen(FRAMAC, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
108 |
(stdout, stderr) = p.communicate() |
|
109 |
res = p.wait() |
|
110 |
if res != 0: |
|
111 |
return (None, "PARSE_"+str(res), None) |
|
112 |
FRAMAC=["frama-c", "-wp", "-wp-prover", "CVC4,alt-ergo,z3,coq", temp+"/top.c", "-wp-par", "2", "-wp-model", "ref", """-wp-tactic="Require Why3. intros. hnf. repeat split;try why3 \"CVC3\" timelimit 10;try why3 \"Z3\" timelimit 10;why3 \"CVC4\" timelimit 10" """, "-wp-script", temp+"/top.coq", "-wp-no-let"] |
|
113 |
#"-wp-rte", |
|
114 |
p = subprocess.Popen(FRAMAC, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|
115 |
(stdout, stderr) = p.communicate() |
|
116 |
res = p.wait() |
|
117 |
if res != 0: |
|
118 |
return (None, "ERR_"+str(res), None) |
|
119 |
m = re_frama_res.search(stdout) |
|
120 |
if not m: |
|
121 |
return (None, "BAD_OUT", None) |
|
122 |
return (lines, str(m.group(1))+"/"+str(m.group(2)), None) |
|
123 |
|
|
124 |
|
|
125 |
def parseFile(inp, todo): |
|
126 |
lines = inp.readlines() |
|
127 |
|
|
128 |
temp = tempfile.mkdtemp(prefix="contracts_") |
|
129 |
res = "" |
|
130 |
data = None |
|
131 |
ok = False |
|
132 |
for f in todo: |
|
133 |
x = [[]] |
|
134 |
(newlines, r, cmd) = f(lines[:], temp) |
|
135 |
res += "{:8} ".format(r[:8]) |
|
136 |
if newlines: |
|
137 |
lines = newlines |
|
138 |
if cmd == "STOP": |
|
139 |
break |
|
140 |
if cmd == "KEEP": |
|
141 |
ok = True |
|
142 |
if ok: |
|
143 |
res += "WRITE" |
|
144 |
data = "".join(lines) |
|
145 |
shutil.rmtree(temp) |
|
146 |
|
|
147 |
return (res, data) |
|
148 |
|
|
149 |
TODO=[modProperties, addEnsures, addK, compileLustre, framac] |
|
150 |
|
|
151 |
LENGTH=40 |
|
152 |
|
|
153 |
target="./generated/" |
|
154 |
|
|
155 |
if os.path.exists(target): |
|
156 |
shutil.rmtree(target) |
|
157 |
|
|
158 |
orig = "tests_new" |
|
159 |
for root, dirs, files in os.walk(orig): |
|
160 |
short = root[len(orig):] |
|
161 |
os.mkdir(target+"/"+short) |
|
162 |
for x in files: |
|
163 |
if not x.endswith(".lus"): |
|
164 |
continue |
|
165 |
inp = open(root+"/"+x, "r") |
|
166 |
(res, data) = parseFile(inp, TODO) |
|
167 |
inp.close() |
|
168 |
if data: |
|
169 |
out = open(target+"/"+short+"/"+x, "w") |
|
170 |
out.write(data) |
|
171 |
out.close() |
|
172 |
print(("Process {0:"+str(LENGTH)+"} : {1}").format(("./"+short+"/"+x)[:LENGTH], res)) |
|
173 |
sys.stdout.flush() |
Also available in: Unified diff
Move gen_contracts.py