Coverage for kye/parser/flatten_ast.py: 12%
60 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-13 15:17 -0700
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-13 15:17 -0700
1from kye.parser.kye_ast import *
3def define_models(node: AST, models):
5 if isinstance(node, Model):
6 assert node.type_ref not in models
7 models[node.type_ref] = {
8 'name': node.name,
9 'indexes': [idx.edges for idx in node.indexes],
10 'edges': {},
11 }
13 elif isinstance(node, Edge):
14 assert node.type_ref in models
15 assert node.type_ref not in models[node.type_ref]['edges']
16 edge = {
17 'type': node.typ.type_ref,
18 }
19 if node.cardinality in ('?', '*'):
20 edge['nullable'] = True
21 if node.cardinality in ('+', '*'):
22 edge['multiple'] = True
24 models[node.type_ref]['edges'][node.name] = edge
26 elif isinstance(node, TypeRef):
27 assert node.type_ref not in models
28 referenced_type = node.scope[node.name]
29 extends = referenced_type.type_ref if isinstance(referenced_type, AST) else node.name
31 models[node.type_ref] = {
32 'extends': extends,
33 }
35 if node.index:
36 models[node.type_ref]['indexes'] = [ node.index.edges ]
38 for child in node.children:
39 define_models(child, models)
41 return models
43def get_models_to_simplify(models):
44 simplify = {}
45 for ref, model in models.items():
46 if set(model.keys()) == {'extends'}:
47 simplify[ref] = model['extends']
48 elif set(model.keys()) == {'extends','indexes'}:
49 assert len(model['indexes']) == 1
50 referenced_indexes = models[model['extends']]['indexes']
51 if len(referenced_indexes) == 1 and tuple(referenced_indexes[0]) == tuple(model['indexes'][0]):
52 simplify[ref] = model['extends']
54 return simplify
56def update_models(models, simplify):
57 for model in models.values():
58 if 'extends' in model and model['extends'] in simplify:
59 model['extends'] = simplify[model['extends']]
60 for edge in model.get('edges',{}).values():
61 if edge.get('type') in simplify:
62 edge['type'] = simplify[edge['type']]
64 for ref in simplify.keys():
65 if ref in models:
66 del models[ref]
68EBRAKE = 10
70def simplify_models(models):
71 simplify = {}
72 ebrake = EBRAKE
73 while ebrake == EBRAKE or (len(to_simplify) > 0 and ebrake > 0):
74 to_simplify = get_models_to_simplify(models)
75 simplify.update(to_simplify)
76 update_models(models, simplify)
77 ebrake -= 1
79 assert ebrake > 0, "Simplify loop ebrake triggered"
81def flatten_ast(ast: AST):
82 models = {}
83 define_models(ast, models)
84 simplify_models(models)
85 return models