3 from .common import NodeProperty
4 from lib.utils import Schema, SourceLogger
11 self.__tab[lazy.get_key()] = lazy
14 return self.__tab[key] if key in self.__tab else None
16 def __setitem__(self, key, val):
20 def __getitem__(self, key):
22 return lz.resolve_get()
27 LazyTypes = Schema.Union(NodeValue)
28 Syntax = Schema(ast.Attribute, attr=LazyTypes, value=ast.Name)
30 def __init__(self, source, type, target, env):
36 def __resolve_type(self):
37 if self.type == Lazy.NodeValue:
38 return NodeProperty.Value
41 def resolve_get(self):
42 node = self.env.get_node(self.target)
44 accessor = self.__resolve_type()
48 status = NodeProperty.Status[node]
49 if status == "Updating":
50 tok = NodeProperty.Token[self.source]
51 SourceLogger.warn(self.source, tok,
52 f"cyclic dependency detected: {self.source._name} <-> {self.target}." +
53 f"Reusing cached value, maybe staled.")
57 return accessor[node] if accessor else None
59 def resolve_set(self, val):
60 node = self.env.get_node(self.target)
61 accessor = self.__resolve_type()
63 if NodeProperty.Readonly[node]:
64 raise self.source.config_error(
65 f"{self.target} is readonly")
70 raise self.source.config_error(
71 f"invalid type {self.type} for {self.target}")
74 return Lazy.get_key_from(self.type, self.target)
77 def get_key_from(type, target):
78 return f"{type}${target}"
81 def from_astn(cfgnode, astn):
82 if Lazy.Syntax != astn:
86 target = astn.value.id
88 return Lazy.from_type(cfgnode, type_, target)
91 def from_type(cfgnode, type_, target):
92 key = Lazy.get_key_from(type_, target)
93 lz = cfgnode._lazy_table.get(key)
98 lz = Lazy(cfgnode, type_, target, cfgnode._env)
99 cfgnode._lazy_table.put(lz)