diff options
author | Daniel Mensinger <daniel@mensinger-ka.de> | 2019-09-04 22:27:40 +0200 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2019-09-04 15:05:41 -0700 |
commit | bd37147b4b46081c58e0b15f6a0f0123099b27b1 (patch) | |
tree | c24d6a2ef591819f7e9c37e34a5329649381474b /mesonbuild/ast/interpreter.py | |
parent | 51a601c2ee9717381ef6574c9ca5ccfc583c930e (diff) | |
download | meson-bd37147b4b46081c58e0b15f6a0f0123099b27b1.zip meson-bd37147b4b46081c58e0b15f6a0f0123099b27b1.tar.gz meson-bd37147b4b46081c58e0b15f6a0f0123099b27b1.tar.bz2 |
mintro: Fix resolving nodes in kwargs (fixes #5884)
Diffstat (limited to 'mesonbuild/ast/interpreter.py')
-rw-r--r-- | mesonbuild/ast/interpreter.py | 108 |
1 files changed, 66 insertions, 42 deletions
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 6684ca4..4d810fc 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -245,7 +245,7 @@ class AstInterpreter(interpreterbase.InterpreterBase): self.reverse_assignment[node.value.ast_id] = node self.assign_vals[node.var_name] = [self.evaluate_statement(node.value)] # Evaluate the value just in case - def flatten_args(self, args: Any, include_unknown_args: bool = False, id_loop_detect: Optional[List[str]] = None) -> List[str]: + def resolve_node(self, node: BaseNode, include_unknown_args: bool = False, id_loop_detect: Optional[List[str]] = None) -> Optional[Any]: def quick_resolve(n: BaseNode, loop_detect: Optional[List[str]] = None) -> Any: if loop_detect is None: loop_detect = [] @@ -260,74 +260,98 @@ class AstInterpreter(interpreterbase.InterpreterBase): if id_loop_detect is None: id_loop_detect = [] - flattend_args = [] + result = None + + if not isinstance(node, BaseNode): + return None + + assert(hasattr(node, 'ast_id')) + if node.ast_id in id_loop_detect: + return None # Loop detected + id_loop_detect += [node.ast_id] - if isinstance(args, BaseNode): - assert(hasattr(args, 'ast_id')) - if args.ast_id in id_loop_detect: - return [] # Loop detected - id_loop_detect += [args.ast_id] + # Try to evealuate the value of the node + if isinstance(node, IdNode): + result = quick_resolve(node) - if isinstance(args, ArrayNode): - args = [x for x in args.args.arguments] + elif isinstance(node, ElementaryNode): + result = node.value - elif isinstance(args, ArgumentNode): - args = [x for x in args.arguments] + elif isinstance(node, ArrayNode): + result = [x for x in node.args.arguments] - elif isinstance(args, ArithmeticNode): - if args.operation != 'add': - return [] # Only handle string and array concats - l = quick_resolve(args.left) - r = quick_resolve(args.right) + elif isinstance(node, ArgumentNode): + result = [x for x in node.arguments] + + elif isinstance(node, ArithmeticNode): + if node.operation != 'add': + return None # Only handle string and array concats + l = quick_resolve(node.left) + r = quick_resolve(node.right) if isinstance(l, str) and isinstance(r, str): - args = [l + r] # String concatination detected + result = l + r # String concatination detected else: - args = self.flatten_args(l, include_unknown_args, id_loop_detect) + self.flatten_args(r, include_unknown_args, id_loop_detect) + result = self.flatten_args(l, include_unknown_args, id_loop_detect) + self.flatten_args(r, include_unknown_args, id_loop_detect) - elif isinstance(args, MethodNode): - src = quick_resolve(args.source_object) - margs = self.flatten_args(args.args, include_unknown_args, id_loop_detect) + elif isinstance(node, MethodNode): + src = quick_resolve(node.source_object) + margs = self.flatten_args(node.args, include_unknown_args, id_loop_detect) try: if isinstance(src, str): - args = [self.string_method_call(src, args.name, margs)] + result = self.string_method_call(src, node.name, margs) elif isinstance(src, bool): - args = [self.bool_method_call(src, args.name, margs)] + result = self.bool_method_call(src, node.name, margs) elif isinstance(src, int): - args = [self.int_method_call(src, args.name, margs)] + result = self.int_method_call(src, node.name, margs) elif isinstance(src, list): - args = [self.array_method_call(src, args.name, margs)] + result = self.array_method_call(src, node.name, margs) elif isinstance(src, dict): - args = [self.dict_method_call(src, args.name, margs)] - else: - return [] + result = self.dict_method_call(src, node.name, margs) except mesonlib.MesonException: - return [] + return None + + # Ensure that the result is fully resolved (no more nodes) + if isinstance(result, BaseNode): + result = self.resolve_node(result, include_unknown_args, id_loop_detect) + elif isinstance(result, list): + new_res = [] + for i in result: + if isinstance(i, BaseNode): + resolved = self.resolve_node(i, include_unknown_args, id_loop_detect) + if resolved is not None: + new_res += self.flatten_args(resolved, include_unknown_args, id_loop_detect) + else: + new_res += [i] + result = new_res + + return result + def flatten_args(self, args: Any, include_unknown_args: bool = False, id_loop_detect: Optional[List[str]] = None) -> List[Any]: # Make sure we are always dealing with lists if not isinstance(args, list): args = [args] + flattend_args = [] + # Resolve the contents of args for i in args: - if isinstance(i, IdNode): - flattend_args += self.flatten_args(quick_resolve(i), include_unknown_args, id_loop_detect) - elif isinstance(i, (ArrayNode, ArgumentNode, ArithmeticNode, MethodNode)): - flattend_args += self.flatten_args(i, include_unknown_args, id_loop_detect) - elif isinstance(i, mparser.ElementaryNode): - flattend_args += [i.value] - elif isinstance(i, (str, bool, int, float)): - flattend_args += [i] - elif include_unknown_args: + if isinstance(i, BaseNode): + resolved = self.resolve_node(i, include_unknown_args, id_loop_detect) + if resolved is not None: + if not isinstance(resolved, list): + resolved = [resolved] + flattend_args += resolved + elif isinstance(i, (str, bool, int, float)) or include_unknown_args: flattend_args += [i] return flattend_args def flatten_kwargs(self, kwargs: object, include_unknown_args: bool = False): flattend_kwargs = {} for key, val in kwargs.items(): - if isinstance(val, ElementaryNode): - flattend_kwargs[key] = val.value - elif isinstance(val, (ArrayNode, ArgumentNode, ArithmeticNode, MethodNode)): - flattend_kwargs[key] = self.flatten_args(val, include_unknown_args) + if isinstance(val, BaseNode): + resolved = self.resolve_node(val, include_unknown_args) + if resolved is not None: + flattend_kwargs[key] = resolved elif isinstance(val, (str, bool, int, float)) or include_unknown_args: flattend_kwargs[key] = val return flattend_kwargs |