Coverage for kye/parser/type_evaluation.py: 40%

60 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-11-21 15:13 -0700

1from __future__ import annotations 

2from typing import Optional 

3from kye.parser.kye_ast import * 

4from kye.parser.types import * 

5 

6class TypeEvaluation: 

7 name: str 

8 env: Environment 

9 

10 def __init__(self, env: Environment, name: str): 

11 self.name = name 

12 self.env = ChildEnvironment(name=name, parent=env) 

13 

14 @property 

15 def type(self): 

16 return self.env.parent.local.get(self.name) 

17 

18 def evaluate(self): 

19 """ Evaluate Type Expressions to generate a type """ 

20 raise NotImplementedError() 

21 

22 def __repr__(self): 

23 return repr(self.env) 

24 

25class ContainerTypeEvaluation(TypeEvaluation): 

26 ast: ContainedDefinitions 

27 children: list[TypeEvaluation] 

28 

29 def __init__(self, env: Environment, ast: ContainedDefinitions): 

30 name = ast.name if isinstance(ast, Definition) else None 

31 super().__init__(env, name=name) 

32 self.ast = ast 

33 self.children = [ get_type_evaluation(self.env, child) for child in ast.children ] 

34 self.env.parent.define_type( 

35 name=self.name, 

36 indexes=self.ast.indexes if isinstance(self.ast, ModelDefinition) else [], 

37 edges={ 

38 child.name: self.env[child.name] 

39 for child in self.children 

40 } 

41 ) 

42 self.env.freeze() 

43 

44 def evaluate(self): 

45 for child in self.children: 

46 child.evaluate() 

47 

48def evaluate_type(ast: Expression, env: Environment) -> Type: 

49 if isinstance(ast, Identifier): 

50 if ast.name not in env: 

51 raise KeyError(f'Unknown reference to "{ast.name}" ({repr(ast.meta)})') 

52 else: 

53 typ = env[ast.name] 

54 if typ is None: 

55 return Type(extends='.'.join(env.get_path(ast.name))) 

56 else: 

57 return typ 

58 

59 

60class ExpressionTypeEvaluation(TypeEvaluation): 

61 ast: ExpressionDefinition 

62 expr: Expression 

63 

64 def __init__(self, env: Environment, ast: ExpressionDefinition): 

65 super().__init__(env, name=ast.name) 

66 self.ast = ast 

67 self.expr = ast.type 

68 self.env.parent.define(self.name) 

69 

70 def evaluate(self): 

71 evaluate_type(self.expr, self.env) 

72 

73 

74def assign_scopes(env: Environment, ast: AST): 

75 if isinstance(ast, Definition): 

76 env[ast.name] = None 

77 if isinstance(ast, ModelDefinition): 

78 env = ChildEnvironment(ast.name, parent=env) 

79 for child in ast.children: 

80 assign_scopes(env, child) 

81 setattr(ast, 'env', env) 

82 

83def get_type_evaluation( 

84 env: Environment, 

85 ast: AST, 

86 ) -> TypeEvaluation: 

87 

88 if isinstance(ast, ContainedDefinitions): 

89 return ContainerTypeEvaluation(env, ast) 

90 elif isinstance(ast, ExpressionDefinition): 

91 return ExpressionTypeEvaluation(env, ast) 

92 else: 

93 raise RuntimeError(f'Cannot evaluate {ast}') 

94 

95 # def get_unresolved_references(self): 

96 # if self.expr is not None: 

97 # for _, child in self.ast.traverse(): 

98 # if isinstance(child, Identifier) and self.env[child.name] is None: 

99 # yield child.name 

100 # for child in self.children: 

101 # yield from child.get_unresolved_references() 

102 

103 # def evaluate(self): 

104 # if self.ast is None: 

105 # return Type(self.name) 

106 # if isinstance(self.ast, ModuleDefinitions): 

107 # self.evaluate_module() 

108 # if isinstance(self.ast, ModelDefinition): 

109 # self.evaluate_model() 

110 # elif isinstance(self.ast, AliasDefinition): 

111 # self.evaluate_expression(self.ast.type) 

112 # else: 

113 # raise RuntimeError(f'Cannot evaluate {self.ast}') 

114 

115 # def evaluate_module(self): 

116 # pass 

117 

118 # def evaluate_model(self): 

119 # pass 

120 

121 # def evaluate_expression(self, ast: Expression): 

122 # if isinstance(ast, Identifier): 

123 # return self.env[ast.name].evaluate() 

124