-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathdbscheme_gen.py
104 lines (91 loc) · 3.19 KB
/
dbscheme_gen.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
'''Tool for generating the dbscheme from the relation tree described in
'master.py' and the part scheme in dbscheme.template'''
from semmle.util import fprintf
from semmle import util
from semmle.python import master
import sys
import os.path
def write(nodes, out):
nodes = set(nodes)
#Emit in sorted order to reduce diffs.
sorted_nodes = sorted(nodes, key = lambda n: n.__name__)
fprintf(out, '\n')
for n in sorted_nodes:
if n.layout:
fprintf(out, '\n')
for name, f_t, offset, _, _, _ in n.layout:
fprintf(out, '/* <Field> %s.%s = %s, %s */\n',
n.ql_name(), name, offset, f_t.__name__)
if n.parents:
fprintf(out, '/* <Parent> %s = %s */\n',
n.ql_name(), n.parents.ql_name())
parents = set()
for n in sorted_nodes:
if n.is_sub_type() or n.is_union_type():
continue
fprintf(out, u'%s(', n.relation_name())
if n.__name__ == "bool":
fields = []
else:
fields = [ n.db_key('id') ]
if n.is_case_type():
fields.append('int kind: int ref')
if n.parents:
parents.add(n.parents)
if n.unique_parent:
fields.append('unique int parent : %s ref' % n.parents.db_name())
else:
fields.append('int parent : %s ref' % n.parents.db_name())
fields.append('int idx : int ref')
fprintf(out, ',\n '.join(fields))
fprintf(out, ');\n\n')
nodes = nodes | parents
sorted_nodes = sorted(nodes, key = lambda n: n.__name__)
for n in sorted_nodes:
if n.is_case_type():
fprintf(out, 'case %s.kind of\n ', n.db_name())
subtypes = sorted(n.subclasses, key = lambda x : x.index)
body = '\n| '.join(['%s = %s' % (s.index, s.db_name())
for s in subtypes])
fprintf(out, '%s;\n\n' % body)
for n in sorted_nodes:
if n.is_union_type():
fprintf(out, '%s = ', n.db_name())
body = ' | '.join(sorted([item.db_name() for item in n.types]))
fprintf(out, '%s;\n\n' % body)
HEADER = '''/*
* This dbscheme is auto-generated by '%s'.
* WARNING: Any modifications to this file will be lost.
* Relations can be changed by modifying master.py or
* by adding rules to dbscheme.template
*/
'''
AUTO_GEN_END = '''
/*
* End of auto-generated part
*/
'''
def main():
run(master)
def run(nodes_module):
use_file = len(sys.argv) > 1
if use_file:
out = open(sys.argv[1], 'w', encoding='utf-8')
else:
out = sys.stdout
try:
nodes = nodes_module.all_nodes()
this_dir, _ = os.path.split(sys.argv[0])
with open(os.path.join(this_dir, 'dbscheme.template')) as template_file:
t0, t1 = template_file.read().split('$AST_SCHEME$')
out.write(HEADER % '/'.join(__file__.split(os.path.sep)[-2:]))
out.write(t0)
out.write(util.AUTO_GEN_STRING)
write(nodes.values(), out)
out.write(AUTO_GEN_END)
out.write(t1)
finally:
if use_file:
out.close()
if __name__ == '__main__':
main()