This method currently supports lowering simple list comprehensions to the MLIR. By simple, we mean expressions like `[expr(iter) for iter in iterable]` or `myList = [exprThatReturns(iter) for iter in iterable]`, optionally with `if` filter clause.
(self, node)
| 4039 | self.emitFatalError(f"unknown function call", node) |
| 4040 | |
| 4041 | def visit_ListComp(self, node): |
| 4042 | """This method currently supports lowering simple list comprehensions to |
| 4043 | the MLIR. |
| 4044 | |
| 4045 | By simple, we mean expressions like `[expr(iter) for iter in iterable]` |
| 4046 | or `myList = [exprThatReturns(iter) for iter in iterable]`, optionally |
| 4047 | with `if` filter clause. |
| 4048 | """ |
| 4049 | if len(node.generators) > 1: |
| 4050 | self.emitFatalError( |
| 4051 | "CUDA-Q only supports single generators for list comprehension.", |
| 4052 | node) |
| 4053 | |
| 4054 | if_clauses = node.generators[0].ifs |
| 4055 | hasFilter = len(if_clauses) > 0 |
| 4056 | |
| 4057 | self.visit(node.generators[0].iter) |
| 4058 | iterable = self.popValue() |
| 4059 | orig_iterable_type = iterable.type |
| 4060 | if cc.StdvecType.isinstance(iterable.type): |
| 4061 | iterableSize = cc.StdvecSizeOp(self.getIntegerType(), |
| 4062 | iterable).result |
| 4063 | iterTy = cc.StdvecType.getElementType(iterable.type) |
| 4064 | iterArrPtrTy = cc.PointerType.get(cc.ArrayType.get(iterTy)) |
| 4065 | iterable = cc.StdvecDataOp(iterArrPtrTy, iterable).result |
| 4066 | elif quake.VeqType.isinstance(iterable.type): |
| 4067 | iterableSize = quake.VeqSizeOp(self.getIntegerType(), |
| 4068 | iterable).result |
| 4069 | iterTy = quake.RefType.get() |
| 4070 | else: |
| 4071 | self.emitFatalError( |
| 4072 | "CUDA-Q only supports list comprehension on ranges and arrays", |
| 4073 | node) |
| 4074 | |
| 4075 | def process_void_list(): |
| 4076 | # NOTE: This does not actually create a valid value, and will fail |
| 4077 | # if something tries to use the value that this was supposed to |
| 4078 | # create later on. Keeping this to keep existing functionality, but |
| 4079 | # this is a bit questionable. Aside from no list being produced, |
| 4080 | # this should work regardless of what we iterate over or what |
| 4081 | # expression we evaluate. |
| 4082 | self.emitWarning( |
| 4083 | "produced elements in list comprehension contain None - " |
| 4084 | "expression will be evaluated but no list is generated", node) |
| 4085 | forNode = ast.For() |
| 4086 | forNode.iter = node.generators[0].iter |
| 4087 | forNode.target = node.generators[0].target |
| 4088 | forNode.body = [node.elt] |
| 4089 | forNode.orelse = [] |
| 4090 | forNode.lineno = node.lineno |
| 4091 | # This loop could be marked as invariant if we didn't use |
| 4092 | # `visit_For`, but that would be premature optimization. |
| 4093 | self.visit_For(forNode) |
| 4094 | |
| 4095 | def evalFilter(): |
| 4096 | cond = None |
| 4097 | for if_node in if_clauses: |
| 4098 | self.visit(if_node) |
nothing calls this directly
no test coverage detected