X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/bcc25888b3299758ad36721530cca3b899b7166c..c043fa535514a76091be87a45ad472a505f9dd33:/lunaix-os/scripts/build-tools/lcfg2/lazy.py diff --git a/lunaix-os/scripts/build-tools/lcfg2/lazy.py b/lunaix-os/scripts/build-tools/lcfg2/lazy.py new file mode 100644 index 0000000..1c634fd --- /dev/null +++ b/lunaix-os/scripts/build-tools/lcfg2/lazy.py @@ -0,0 +1,102 @@ +import ast + +from .common import NodeProperty +from lib.utils import Schema, SourceLogger + +class LazyLookup: + def __init__(self): + self.__tab = {} + + def put(self, lazy): + self.__tab[lazy.get_key()] = lazy + + def get(self, key): + return self.__tab[key] if key in self.__tab else None + + def __setitem__(self, key, val): + lz = self.__tab[key] + lz.resolve_set(val) + + def __getitem__(self, key): + lz = self.__tab[key] + return lz.resolve_get() + +class Lazy: + NodeValue = 'val' + + LazyTypes = Schema.Union(NodeValue) + Syntax = Schema(ast.Attribute, attr=LazyTypes, value=ast.Name) + + def __init__(self, source, type, target, env): + self.target = target + self.type = type + self.env = env + self.source = source + + def __resolve_type(self): + if self.type == Lazy.NodeValue: + return NodeProperty.Value + return None + + def resolve_get(self): + node = self.env.get_node(self.target) + + accessor = self.__resolve_type() + if not accessor: + return None + + status = NodeProperty.Status[node] + if status == "Updating": + tok = NodeProperty.Token[self.source] + SourceLogger.warn(self.source, tok, + f"cyclic dependency detected: {self.source._name} <-> {self.target}." + + f"Reusing cached value, maybe staled.") + else: + node.update() + + return accessor[node] if accessor else None + + def resolve_set(self, val): + node = self.env.get_node(self.target) + accessor = self.__resolve_type() + + if NodeProperty.Readonly[node]: + raise self.source.config_error( + f"{self.target} is readonly") + + if accessor: + accessor[node] = val + else: + raise self.source.config_error( + f"invalid type {self.type} for {self.target}") + + def get_key(self): + return Lazy.get_key_from(self.type, self.target) + + @staticmethod + def get_key_from(type, target): + return f"{type}${target}" + + @staticmethod + def from_astn(cfgnode, astn): + if Lazy.Syntax != astn: + return None + + type_ = astn.attr + target = astn.value.id + + return Lazy.from_type(cfgnode, type_, target) + + @staticmethod + def from_type(cfgnode, type_, target): + key = Lazy.get_key_from(type_, target) + lz = cfgnode._lazy_table.get(key) + + if lz: + return key + + lz = Lazy(cfgnode, type_, target, cfgnode._env) + cfgnode._lazy_table.put(lz) + + return key +