def visit_Call(self, node): fname = self.visit(node.func) fndef = node.scopes.find(fname) if isinstance(fndef, ast.ClassDef): return self._visit_struct_literal(node, fname, fndef) vargs = [] # visited args if node.args: vargs += [self.visit(a) for a in node.args] if node.keywords: vargs += [self.visit(kw.value) for kw in node.keywords] ret = self._dispatch(node, fname, vargs) if ret is not None: return ret # Check if some args need to be passed by reference ref_args = [] if fndef and hasattr(fndef, "args"): for varg, fnarg, node_arg in zip(vargs, fndef.args.args, node.args): if is_reference(fnarg) and not is_reference(node_arg): ref_args.append(f"&{varg}") else: ref_args.append(varg) else: ref_args = vargs args = ", ".join(ref_args) return f"{fname}({args})"
def visit_Return(self, node): fndef = None for scope in node.scopes: if isinstance(scope, ast.FunctionDef): fndef = scope break if node.value: ret = self.visit(node.value) if fndef: if getattr(fndef, "rust_pyresult_type", False): # TODO: Design a more robust solution for this # For now, PyResult and references don't mix if ret.startswith("&"): ret = ret[1:] ret = f"Ok({ret})" return_type = self._typename_from_annotation(fndef, attr="returns") value_type = get_inferred_rust_type(node.value) if is_reference(node.value) and not getattr( fndef.returns, "rust_needs_reference", True): # TODO: Handle other container types ret = f"{ret}.to_vec()" if return_type != value_type and value_type is not None: return f"return {ret} as {return_type};" return f"return {ret};" if fndef: if getattr(fndef, "rust_pyresult_type", False): return "return Ok(())" return "return;"
def is_rust_reference(node): if not is_reference(node): return False if isinstance(node, ast.Call): definition = node.scopes.find(get_id(node.func)) needs_reference = getattr(definition, "rust_return_needs_reference", True) return needs_reference return True
def visit_Call(self, node): fname = self.visit(node.func) fndef = node.scopes.find(fname) if isinstance(fndef, ast.ClassDef): return self._visit_struct_literal(node, fname, fndef) vargs = [] # visited args if node.args: vargs += [self.visit(a) for a in node.args] if node.keywords: vargs += [self.visit(kw.value) for kw in node.keywords] ret = self._dispatch(node, fname, vargs) node_result_type = getattr(node, "result_type", False) node_func_result_type = getattr(node.func, "result_type", False) if ret is not None: if ret.startswith("std::process::exit("): node_result_type = False unwrap = "?" if node_result_type or node_func_result_type else "" return f"{ret}{unwrap}" # Check if some args need to be passed by reference ref_args = [] if fndef and hasattr(fndef, "args"): for varg, fnarg, node_arg in zip(vargs, fndef.args.args, node.args): if is_reference(fnarg) and not is_reference(node_arg): ref_args.append(f"&{varg}") else: ref_args.append(varg) else: ref_args = vargs args = ", ".join(ref_args) unwrap = "?" if node_result_type or node_func_result_type else "" return f"{fname}({args}){unwrap}"
def visit_Return(self, node): self.generic_visit(node) if node.value: fndef = None for scope in node.scopes: if isinstance(scope, ast.FunctionDef): fndef = scope break if fndef: if is_reference(node.value): mut = is_mutable(node.scopes, get_id(node.value)) fndef.returns.rust_needs_reference = not mut fndef.rust_return_needs_reference = ( fndef.returns.rust_needs_reference) return node
def visit_Return(self, node): if node.value: ret = self.visit(node.value) fndef = None for scope in node.scopes: if isinstance(scope, ast.FunctionDef): fndef = scope break if fndef: return_type = self._typename_from_annotation(fndef, attr="returns") value_type = get_inferred_rust_type(node.value) if is_reference(node.value) and not getattr( fndef.returns, "rust_needs_reference", True): # TODO: Handle other container types ret = f"{ret}.to_vec()" if return_type != value_type and value_type is not None: return f"return {ret} as {return_type};" return f"return {ret};" return "return;"
def visit_For(self, node): if hasattr(node.iter, "id"): definition = node.scopes.find(node.iter.id) if is_reference(definition): node.target.needs_dereference = True return node