Coverage for kye/parser/flatten_ast.py: 0%

60 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-01 16:37 -0700

1from kye.parser.kye_ast import * 

2 

3def define_models(node: AST, models): 

4 

5 if isinstance(node, ModelDefinition): 

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 } 

12 

13 elif isinstance(node, EdgeDefinition): 

14 assert node.type_ref in models 

15 assert node.type_ref not in models[node.type_ref]['edges'] 

16 edge = { 

17 'type': node.type.type_ref, 

18 } 

19 if node.cardinality in ('?', '*'): 

20 edge['nullable'] = True 

21 if node.cardinality in ('+', '*'): 

22 edge['multiple'] = True 

23 

24 models[node.type_ref]['edges'][node.name] = edge 

25 

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 

30 

31 models[node.type_ref] = { 

32 'extends': extends, 

33 } 

34 

35 if node.index: 

36 models[node.type_ref]['indexes'] = [ node.index.edges ] 

37 

38 for child in node.children: 

39 define_models(child, models) 

40 

41 return models 

42 

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'] 

53 

54 return simplify 

55 

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']] 

63 

64 for ref in simplify.keys(): 

65 if ref in models: 

66 del models[ref] 

67 

68EBRAKE = 10 

69 

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 

78 

79 assert ebrake > 0, "Simplify loop ebrake triggered" 

80 

81def flatten_ast(ast: AST): 

82 models = {} 

83 define_models(ast, models) 

84 simplify_models(models) 

85 return models