3 from lib.utils import Schema
5 from .common import NodeProperty
10 func=Schema(ast.Name),
13 WhenTogglerItem = Schema(
16 ops=[Schema.Union(ast.Is, ast.IsNot)],
17 comparators=[ast.Constant])
24 values=Schema.List(WhenTogglerItem))))
26 class ConfigNodeASTRewriter(ast.NodeTransformer):
29 def __init__(self, cfg_node):
32 self.__cfg_node = cfg_node
34 def __subscript_accessor(self, name, ctx, token):
36 value=ast.Name("__lzLut__", ctx=ast.Load()),
37 slice=ast.Constant(name),
41 def __gen_accessor(self, orig):
42 key = Lazy.from_astn(self.__cfg_node, orig)
44 return self.generic_visit(orig)
46 return self.__subscript_accessor(key, orig.ctx, orig)
48 def __gen_dependency(self, node):
49 cfgn = self.__cfg_node
50 dep_expr = NodeProperty.Dependency[cfgn]
52 NodeProperty.Dependency[cfgn] = node
55 if not isinstance(dep_expr, ast.expr):
56 raise cfgn.config_error(
57 f"invalid dependency state: {dep_expr}")
59 dep_expr = ast.BoolOp(ast.And(), [dep_expr, node])
60 NodeProperty.Dependency[cfgn] = dep_expr
62 def __gen_when_expr(self, node):
64 cfgn = self.__cfg_node
66 if RewriteRule.WhenToggler != node:
67 raise cfgn.config_error(
68 f"invalid when(...) expression: {ast.unparse(node)}")
70 if RewriteRule.WhenTogglerItem == node:
73 and_list += node.values
75 for i in range(len(and_list)):
77 operator = item.ops[0]
79 name = Lazy.from_type(cfgn, Lazy.NodeValue, item.left.id)
80 acc = self.__subscript_accessor(name, ast.Load(), node)
82 if isinstance(operator, ast.Is):
85 operator = ast.NotEq()
93 values=[ast.Constant(True), *and_list])
95 expr = NodeProperty.WhenToggle[cfgn]
97 assert isinstance(expr, ast.expr)
98 current = ast.BoolOp(op=ast.Or(), values=[expr, current])
100 NodeProperty.WhenToggle[cfgn] = current
102 def visit_Attribute(self, node):
103 return self.__gen_accessor(node)
105 def visit_Expr(self, node):
108 if RewriteRule.MaybeBuiltin != val:
109 return self.generic_visit(node)
111 # Process marker functions
113 if name == "require":
114 self.__gen_dependency(val.args[0])
116 self.__gen_when_expr(val.args[0])
118 return self.generic_visit(node)
122 def visit_Return(self, node):
123 if NodeProperty.WhenToggle[self.__cfg_node]:
125 return self.generic_visit(node)
127 def visit_Is(self, node):
130 def rewrite(self, node):
131 assert isinstance(node, ast.Module)
132 node = self.visit(node)
134 expr = NodeProperty.WhenToggle[self.__cfg_node]
138 del NodeProperty.WhenToggle[self.__cfg_node]
140 node.body.append(ast.Return(expr, lineno=0, col_offset=0))