-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathdbscheme_gen.py
More file actions
105 lines (92 loc) · 3.26 KB
/
dbscheme_gen.py
File metadata and controls
105 lines (92 loc) · 3.26 KB
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
105
'''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'.
* Run "make dbscheme" in python/extractor/ to regenerate.
* 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()