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
« 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 *
6class TypeEvaluation:
7 name: str
8 env: Environment
10 def __init__(self, env: Environment, name: str):
11 self.name = name
12 self.env = ChildEnvironment(name=name, parent=env)
14 @property
15 def type(self):
16 return self.env.parent.local.get(self.name)
18 def evaluate(self):
19 """ Evaluate Type Expressions to generate a type """
20 raise NotImplementedError()
22 def __repr__(self):
23 return repr(self.env)
25class ContainerTypeEvaluation(TypeEvaluation):
26 ast: ContainedDefinitions
27 children: list[TypeEvaluation]
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()
44 def evaluate(self):
45 for child in self.children:
46 child.evaluate()
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
60class ExpressionTypeEvaluation(TypeEvaluation):
61 ast: ExpressionDefinition
62 expr: Expression
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)
70 def evaluate(self):
71 evaluate_type(self.expr, self.env)
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)
83def get_type_evaluation(
84 env: Environment,
85 ast: AST,
86 ) -> TypeEvaluation:
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}')
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()
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}')
115 # def evaluate_module(self):
116 # pass
118 # def evaluate_model(self):
119 # pass
121 # def evaluate_expression(self, ast: Expression):
122 # if isinstance(ast, Identifier):
123 # return self.env[ast.name].evaluate()