Project

General

Profile

« Previous | Next » 

Revision 6bc919cb

Added by Guillaume Davy almost 10 years ago

Move gen_contracts.py

View differences:

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