def _constructInitialVarnameToType(self): input_types = self._input_types if self._ast_arg.vararg is not None: self._star_args_name = self._ast_arg.vararg.val.arg if self._star_args_name is None: if len(input_types) != len(self._ast_arg.args): raise ConversionException( "Expected %s arguments but got %s" % (len(self._ast_arg.args), len(input_types))) else: if len(input_types) < len(self._ast_arg.args): raise ConversionException( "Expected at least %s arguments but got %s" % (len(self._ast_arg.args), len(input_types))) self._native_args = [] for i in range(len(self._ast_arg.args)): self._varname_to_type[self._ast_arg.args[i].arg] = input_types[i] if not input_types[i].is_empty: self._native_args.append( (self._ast_arg.args[i].arg, input_types[i].getNativePassingType())) self._argnames = [a.arg for a in self._ast_arg.args] if self._star_args_name is not None: star_args_count = len(input_types) - len(self._ast_arg.args) for i in range(len(self._ast_arg.args), len(input_types)): self._native_args.append( ('.star_args.%s' % (i - len(self._ast_arg.args)), input_types[i].getNativePassingType())) starargs_type = native_ast.Struct([ ('f_%s' % i, input_types[i + len(self._ast_arg.args)]) for i in range(star_args_count) ]) self._varname_to_type[self._star_args_name] = starargs_type if self._output_type is not None: self._varname_to_type[FunctionOutput] = typeWrapper( self._output_type) self._functionOutputTypeKnown = FunctionOutput in self._varname_to_type
def named_var_expr(self, name): if self.functionContext._varname_to_type[name] is None: raise ConversionException("variable %s is not in scope here" % name) slot_type = self.functionContext._varname_to_type[name] return TypedExpression(self, native_ast.Expression.StackSlot( name=name, type=slot_type.getNativeLayoutType()), slot_type, isReference=True)
def construct_stackslots_around(self, expr, argnames, stararg_name): to_add = [] destructors = [] for name in argnames: if name is not FunctionOutput and name != stararg_name: if name not in self._varname_to_type: raise ConversionException( "Couldn't find a type for argument %s" % name) slot_type = self._varname_to_type[name] if slot_type.is_empty: # we don't need to generate a stackslot for this value. Whenever we look it up # we'll simply make a void expression pass elif slot_type is not None: context = ExpressionConversionContext(self) if slot_type.is_pod: # we can just copy this into the stackslot directly. no destructor needed context.pushEffect( native_ast.Expression.Store( ptr=native_ast.Expression.StackSlot( name=name, type=slot_type.getNativeLayoutType()), val=(native_ast.Expression.Variable( name=name) if not slot_type.is_pass_by_ref else native_ast.Expression.Variable( name=name).load()))) context.pushEffect( context.isInitializedVarExpr(name).expr.store( native_ast.trueExpr)) else: # need to make a stackslot for this variable # the argument will be a pointer because it's POD var_expr = context.inputArg(slot_type, name) slot_expr = context.named_var_expr(name) slot_type.convert_copy_initialize( context, slot_expr, var_expr) context.pushEffect( context.isInitializedVarExpr(name).expr.store( native_ast.trueExpr)) to_add.append(context.finalize(None)) for name in self._varname_to_type: if name is not FunctionOutput and name != stararg_name: context = ExpressionConversionContext(self) if self._varname_to_type[name] is not None: slot_expr = context.named_var_expr(name) with context.ifelse( context.isInitializedVarExpr(name)) as (true, false): with true: slot_expr.convert_destroy() destructors.append( native_ast.Teardown.Always(expr=context.finalize( None).with_comment("Cleanup for variable %s" % name))) if name not in argnames: # this is a variable in the function that we assigned to. we need to ensure that # the initializer flag is zero context = ExpressionConversionContext(self) context.pushEffect( context.isInitializedVarExpr(name).expr.store( native_ast.falseExpr)) to_add.append(context.finalize(None)) if to_add: expr = native_ast.Expression.Sequence(vals=to_add + [expr]) if destructors: expr = native_ast.Expression.Finally(teardowns=destructors, expr=expr) return expr
def convert_statement_ast(self, ast): if ast.matches.Assign or ast.matches.AugAssign: if ast.matches.Assign: assert len(ast.targets) == 1 op = None target = ast.targets[0] else: target = ast.target op = ast.op if target.matches.Name and target.ctx.matches.Store: varname = target.id if varname not in self._varname_to_type: self._varname_to_type[varname] = None subcontext = ExpressionConversionContext(self) val_to_store = subcontext.convert_expression_ast(ast.value) if val_to_store is None: return subcontext.finalize(None), False if op is not None: if varname not in self._varname_to_type: raise NotImplementedError() else: slot_ref = subcontext.named_var_expr(varname) val_to_store = slot_ref.convert_bin_op( op, val_to_store) if val_to_store is None: return subcontext.finalize(None), False self.generateAssignmentExpr(varname, val_to_store) return subcontext.finalize(None).with_comment("Assign %s" % (varname)), True if target.matches.Subscript and target.ctx.matches.Store: assert target.slice.matches.Index subcontext = ExpressionConversionContext(self) slicing = subcontext.convert_expression_ast(target.value) if slicing is None: return subcontext.finalize(None), False index = subcontext.convert_expression_ast(target.slice.value) if slicing is None: return subcontext.finalize(None), False val_to_store = subcontext.convert_expression_ast(ast.value) if val_to_store is None: return subcontext.finalize(None), False if op is not None: val_to_store = slicing.convert_getitem( index).convert_bin_op(op, val_to_store) if val_to_store is None: return subcontext.finalize(None), False slicing.convert_setitem(index, val_to_store) return subcontext.finalize(None), True if target.matches.Attribute and target.ctx.matches.Store: subcontext = ExpressionConversionContext(self) slicing = subcontext.convert_expression_ast(target.value) attr = target.attr val_to_store = subcontext.convert_expression_ast(ast.value) if val_to_store is None: return subcontext.finalize(None), False if op is not None: input_val = slicing.convert_attribute(attr) if input_val is None: return subcontext.finalize(None), False val_to_store = input_val.convert_bin_op(op, val_to_store) if val_to_store is None: return subcontext.finalize(None), False slicing.convert_set_attribute(attr, val_to_store) return subcontext.finalize(None), True if ast.matches.Return: subcontext = ExpressionConversionContext(self) if ast.value is None: e = subcontext.convert_expression_ast( python_ast.Expr.Num(n=python_ast.NumericConstant.None_())) else: e = subcontext.convert_expression_ast(ast.value) if e is None: return subcontext.finalize(None), False if not self._functionOutputTypeKnown: if self._varname_to_type.get(FunctionOutput) is None: self.markTypesAreUnstable() self._varname_to_type[FunctionOutput] = e.expr_type else: self.upsizeVariableType(FunctionOutput, e.expr_type) if e.expr_type != self._varname_to_type[FunctionOutput]: e = e.convert_to_type(self._varname_to_type[FunctionOutput]) if e is None: return subcontext.finalize(None), False if e.expr_type.is_pass_by_ref: returnTarget = TypedExpression( subcontext, native_ast.Expression.Variable(name=".return"), self._varname_to_type[FunctionOutput], True) returnTarget.convert_copy_initialize(e) subcontext.pushTerminal(native_ast.Expression.Return(arg=None)) else: subcontext.pushTerminal( native_ast.Expression.Return(arg=e.nonref_expr)) return subcontext.finalize(None), False if ast.matches.Expr: subcontext = ExpressionConversionContext(self) result_expr = subcontext.convert_expression_ast(ast.value) return subcontext.finalize(result_expr), result_expr is not None if ast.matches.If: cond_context = ExpressionConversionContext(self) cond = cond_context.convert_expression_ast(ast.test) if cond is None: return cond_context.finalize(None), False cond = cond.toBool() if cond is None: return cond_context.finalize(None), False if cond.expr.matches.Constant: truth_val = cond.expr.val.truth_value() branch, flow_returns = self.convert_statement_list_ast( ast.body if truth_val else ast.orelse) return cond.expr + branch, flow_returns true, true_returns = self.convert_statement_list_ast(ast.body) false, false_returns = self.convert_statement_list_ast(ast.orelse) return (native_ast.Expression.Branch( cond=cond_context.finalize(cond.nonref_expr), true=true, false=false), true_returns or false_returns) if ast.matches.Pass: return native_ast.nullExpr, True if ast.matches.While: cond_context = ExpressionConversionContext(self) cond = cond_context.convert_expression_ast(ast.test) if cond is None: return cond_context.finalize(None), False cond = cond.toBool() if cond is None: return cond_context.finalize(None), False true, true_returns = self.convert_statement_list_ast(ast.body) false, false_returns = self.convert_statement_list_ast(ast.orelse) return (native_ast.Expression.While( cond=cond_context.finalize(cond.nonref_expr), while_true=true, orelse=false), true_returns or false_returns) if ast.matches.Try: raise NotImplementedError() if ast.matches.For: if not ast.target.matches.Name: raise NotImplementedError( "Can't handle multi-variable loop expressions") target_var_name = ast.target.id # create a variable to hold the iterator, and instantiate it there iter_varname = target_var_name + ".iter." + str(ast.line_number) iterator_setup_context = ExpressionConversionContext(self) to_iterate = iterator_setup_context.convert_expression_ast( ast.iter) if to_iterate is None: return iterator_setup_context.finalize(to_iterate), False iterator_object = to_iterate.convert_method_call( "__iter__", (), {}) if iterator_object is None: return iterator_setup_context.finalize(iterator_object), False self.generateAssignmentExpr(iter_varname, iterator_object) cond_context = ExpressionConversionContext(self) iter_obj = cond_context.named_var_expr(iter_varname) next_ptr, is_populated = iter_obj.convert_next( ) # this conversion is special - it returns two values with cond_context.ifelse(is_populated.nonref_expr) as (if_true, if_false): with if_true: self.generateAssignmentExpr(target_var_name, next_ptr) true, true_returns = self.convert_statement_list_ast(ast.body) false, false_returns = self.convert_statement_list_ast(ast.orelse) return (iterator_setup_context.finalize(None) >> native_ast.Expression.While( cond=cond_context.finalize(is_populated), while_true=true, orelse=false), true_returns or false_returns) if ast.matches.Raise: raise NotImplementedError() raise ConversionException("Can't handle python ast Statement.%s" % ast._which)
def convert_expression_ast(self, ast): if ast.matches.Attribute: attr = ast.attr val = self.convert_expression_ast(ast.value) return val.convert_attribute(attr) if ast.matches.Name: assert ast.ctx.matches.Load if ast.id in self.functionContext._varname_to_type: with self.ifelse(self.isInitializedVarExpr(ast.id)) as (true,false): with false: self.pushException(UnboundLocalError, "local variable '%s' referenced before assignment" % ast.id) return self.named_var_expr(ast.id) if ast.id in self.functionContext._free_variable_lookup: return pythonObjectRepresentation(self, self.functionContext._free_variable_lookup[ast.id]) elif ast.id in __builtins__: return pythonObjectRepresentation(self, __builtins__[ast.id]) if ast.id not in self.functionContext._varname_to_type: self.pushException(NameError, "name '%s' is not defined" % ast.id) return None if ast.matches.Num: if ast.n.matches.None_: return pythonObjectRepresentation(self, None) if ast.n.matches.Boolean: return pythonObjectRepresentation(self, bool(ast.n.value)) if ast.n.matches.Int: return pythonObjectRepresentation(self, int(ast.n.value)) if ast.n.matches.Float: return pythonObjectRepresentation(self, float(ast.n.value)) if ast.matches.Str: return pythonObjectRepresentation(self, ast.s) if ast.matches.BoolOp: values = [] for v in ast.values: v = self.convert_expression_ast(v) if v is not None: v = v.toBool() values.append(v) op = ast.op expr_so_far = [] for v in ast.values: v = self.convert_expression_ast(v) if v is None: expr_so_far.append(None) break v = v.toBool() if v is None: expr_so_far.append(None) break expr_so_far.append(v.expr) if expr_so_far[-1] is None: if len(expr_so_far) == 1: return None elif expr_so_far[-1].matches.Constant: if (expr_so_far[-1].val.val and op.matches.Or or (not expr_so_far[-1].val.val) and op.matches.And): #this is a short-circuit if len(expr_so_far) == 1: return expr_so_far[0] return TypedExpression( self, native_ast.Expression.Sequence(expr_so_far), typeWrapper(bool), False ) else: expr_so_far.pop() if not expr_so_far: if op.matches.Or: #must have had all False constants return TypedExpression(self, native_ast.falseExpr, typeWrapper(bool), False) else: #must have had all True constants return TypedExpression(self, native_ast.trueExpr, typeWrapper(bool), False) while len(expr_so_far) > 1: l,r = expr_so_far[-2], expr_so_far[-1] expr_so_far.pop() expr_so_far.pop() if op.matches.And: new_expr = native_ast.Expression.Branch(cond=l, true=r, false=native_ast.falseExpr) else: new_expr = native_ast.Expression.Branch(cond=l, true=native_ast.trueExpr, false=r) expr_so_far.append(new_expr) return TypedExpression(self, expr_so_far[0], typeWrapper(bool), False) if ast.matches.BinOp: l = self.convert_expression_ast(ast.left) if l is None: return None r = self.convert_expression_ast(ast.right) if r is None: return None return l.convert_bin_op(ast.op, r) if ast.matches.UnaryOp: operand = self.convert_expression_ast(ast.operand) return operand.convert_unary_op(ast.op) if ast.matches.Subscript: assert ast.slice.matches.Index val = self.convert_expression_ast(ast.value) if val is None: return None index = self.convert_expression_ast(ast.slice.value) if index is None: return None return val.convert_getitem(index) if ast.matches.Call: l = self.convert_expression_ast(ast.func) if l is None: return None ast_args = ast.args stararg = None for a in ast_args: assert not a.matches.Starred, "not implemented yet" args = [] for a in ast_args: args.append(self.convert_expression_ast(a)) if args[-1] is None: return None return l.convert_call(args) if ast.matches.Compare: assert len(ast.comparators) == 1, "multi-comparison not implemented yet" assert len(ast.ops) == 1 l = self.convert_expression_ast(ast.left) r = self.convert_expression_ast(ast.comparators[0]) return l.convert_bin_op(ast.ops[0], r) if ast.matches.Tuple: raise NotImplementedError("not implemented yet") if ast.matches.IfExp: test = self.convert_expression_ast(ast.test) if test is None: return None test = test.toBool() if test is None: return None with self.ifelse(test) as (true_block, false_block): with true_block: true_res = self.convert_expression_ast(ast.body) with false_block: false_res = self.conversion_exception(ast.orelse) if true_res.expr_type != false_res.expr_type: out_type = typeWrapper(OneOf(true_res.expr_type.typeRepresentation, false_res.expr_type.typeRepresentation)) else: out_type = true_res.expr_type out_slot = self.allocateUninitializedSlot(out_type) with true_block: true_res = true_res.convert_to_type(out_type) out_slot.convert_copy_initialize(true_res) self.markUninitializedSlotInitialized(out_slot) with false_block: false_res = false_res.convert_to_type(out_type) out_slot.convert_copy_initialize(false_res) self.markUninitializedSlotInitialized(out_slot) return out_slot raise ConversionException("can't handle python expression type %s" % ast._which)
def convert_statement_ast(self, ast): if ast.matches.Assign or ast.matches.AugAssign: if ast.matches.Assign: assert len(ast.targets) == 1 op = None target = ast.targets[0] else: target = ast.target op = ast.op if target.matches.Name and target.ctx.matches.Store: varname = target.id if varname not in self._varname_to_type: self._varname_to_type[varname] = None subcontext = ExpressionConversionContext(self) val_to_store = subcontext.convert_expression_ast(ast.value) if val_to_store is None: return subcontext.finalize(None), False if op is not None: if varname not in self._varname_to_type: raise NotImplementedError() else: slot_ref = subcontext.named_var_expr(varname) val_to_store = slot_ref.convert_bin_op( op, val_to_store) if val_to_store is None: return subcontext.finalize(None), False self.upsizeVariableType(varname, val_to_store.expr_type) slot_ref = subcontext.named_var_expr(varname) #convert the value to the target type now that we've upsized it val_to_store = val_to_store.convert_to_type(slot_ref.expr_type) assert val_to_store is not None, "We should always be able to upsize" if slot_ref.expr_type.is_pod: slot_ref.convert_copy_initialize(val_to_store) subcontext.pushEffect( subcontext.isInitializedVarExpr(varname).expr.store( native_ast.trueExpr)) else: with subcontext.ifelse( subcontext.isInitializedVarExpr(varname)) as ( true_block, false_block): with true_block: slot_ref.convert_assign(val_to_store) with false_block: slot_ref.convert_copy_initialize(val_to_store) subcontext.pushEffect( subcontext.isInitializedVarExpr( varname).expr.store(native_ast.trueExpr)) return subcontext.finalize(None).with_comment("Assign %s" % (varname)), True if target.matches.Subscript and target.ctx.matches.Store: assert target.slice.matches.Index subcontext = ExpressionConversionContext(self) slicing = subcontext.convert_expression_ast(target.value) if slicing is None: return subcontext.finalize(None), False index = subcontext.convert_expression_ast(target.slice.value) if slicing is None: return subcontext.finalize(None), False val_to_store = subcontext.convert_expression_ast(ast.value) if val_to_store is None: return subcontext.finalize(None), False if op is not None: val_to_store = slicing.convert_getitem( index).convert_bin_op(op, val_to_store) if val_to_store is None: return subcontext.finalize(None), False slicing.convert_setitem(index, val_to_store) return subcontext.finalize(None), True if target.matches.Attribute and target.ctx.matches.Store: subcontext = ExpressionConversionContext(self) slicing = subcontext.convert_expression_ast(target.value) attr = target.attr val_to_store = subcontext.convert_expression_ast(ast.value) if val_to_store is None: return subcontext.finalize(None), False if op is not None: input_val = slicing.convert_attribute(attr) if input_val is None: return subcontext.finalize(None), False val_to_store = input_val.convert_bin_op(op, val_to_store) if val_to_store is None: return subcontext.finalize(None), False slicing.convert_set_attribute(attr, val_to_store) return subcontext.finalize(None), True if ast.matches.Return: subcontext = ExpressionConversionContext(self) if ast.value is None: e = subcontext.convert_expression_ast( python_ast.Expr.Num(n=python_ast.NumericConstant.None_())) else: e = subcontext.convert_expression_ast(ast.value) if e is None: return subcontext.finalize(None), False if not self._functionOutputTypeKnown: if self._varname_to_type.get(FunctionOutput) is None: self._typesAreUnstable = True self._varname_to_type[FunctionOutput] = e.expr_type else: self.upsizeVariableType(FunctionOutput, e.expr_type) if e.expr_type != self._varname_to_type[FunctionOutput]: e = e.convert_to_type(self._varname_to_type[FunctionOutput]) if e is None: return subcontext.finalize(None), False if e.expr_type.is_pass_by_ref: returnTarget = TypedExpression( subcontext, native_ast.Expression.Variable(name=".return"), self._varname_to_type[FunctionOutput], True) returnTarget.convert_copy_initialize(e) subcontext.pushTerminal(native_ast.Expression.Return(arg=None)) else: subcontext.pushTerminal( native_ast.Expression.Return(arg=e.nonref_expr)) return subcontext.finalize(None), False if ast.matches.Expr: subcontext = ExpressionConversionContext(self) result_expr = subcontext.convert_expression_ast(ast.value) return subcontext.finalize(result_expr), result_expr is not None if ast.matches.If: cond_context = ExpressionConversionContext(self) cond = cond_context.convert_expression_ast(ast.test) if cond is None: return cond.finalize(None), False cond = cond.toBool() if cond is None: return cond.finalize(None), False if cond.expr.matches.Constant: truth_val = cond.expr.val.truth_value() branch, flow_returns = self.convert_statement_list_ast( ast.body if truth_val else ast.orelse) return cond.expr + branch, flow_returns true, true_returns = self.convert_statement_list_ast(ast.body) false, false_returns = self.convert_statement_list_ast(ast.orelse) return (native_ast.Expression.Branch( cond=cond_context.finalize(cond.nonref_expr), true=true, false=false), true_returns or false_returns) if ast.matches.Pass: return native_ast.nullExpr, True if ast.matches.While: cond_context = ExpressionConversionContext(self) cond = cond_context.convert_expression_ast(ast.test) if cond is None: return cond_context.finalize(None), False cond = cond.toBool() if cond is None: return cond_context.finalize(None), False true, true_returns = self.convert_statement_list_ast(ast.body) false, false_returns = self.convert_statement_list_ast(ast.orelse) return (native_ast.Expression.While( cond=cond_context.finalize(cond.nonref_expr), while_true=true, orelse=false), true_returns or false_returns) if ast.matches.Try: raise NotImplementedError() if ast.matches.For: raise NotImplementedError() if ast.matches.Raise: raise NotImplementedError() raise ConversionException("Can't handle python ast Statement.%s" % ast._which)
def convert_expression_ast(self, ast): if ast.matches.Attribute: attr = ast.attr val = self.convert_expression_ast(ast.value) if val is None: return None return val.convert_attribute(attr) if ast.matches.Name: assert ast.ctx.matches.Load if ast.id in self.functionContext._varname_to_type: with self.ifelse(self.isInitializedVarExpr(ast.id)) as (true, false): with false: self.pushException( UnboundLocalError, "local variable '%s' referenced before assignment" % ast.id) return self.named_var_expr(ast.id) if ast.id in self.functionContext._free_variable_lookup: return pythonObjectRepresentation( self, self.functionContext._free_variable_lookup[ast.id]) elif ast.id in __builtins__: return pythonObjectRepresentation(self, __builtins__[ast.id]) if ast.id not in self.functionContext._varname_to_type: self.pushException(NameError, "name '%s' is not defined" % ast.id) return None if ast.matches.Num: if ast.n.matches.None_: return pythonObjectRepresentation(self, None) if ast.n.matches.Boolean: return pythonObjectRepresentation(self, bool(ast.n.value)) if ast.n.matches.Int: return pythonObjectRepresentation(self, int(ast.n.value)) if ast.n.matches.Float: return pythonObjectRepresentation(self, float(ast.n.value)) if ast.matches.Str: return pythonObjectRepresentation(self, ast.s) if ast.matches.BoolOp: def convertBoolOp(depth=0): with self.subcontext() as sc: value = self.convert_expression_ast(ast.values[depth]) value = TypedExpression.asBool(value) if value is not None: if depth == len(ast.values) - 1: sc.expr = value.expr else: tail_expr = convertBoolOp(depth + 1) if ast.op.matches.And: sc.expr = native_ast.Expression.Branch( cond=value.expr, true=tail_expr, false=native_ast.falseExpr) elif ast.op.matches.Or: sc.expr = native_ast.Expression.Branch( cond=value.expr, true=native_ast.trueExpr, false=tail_expr) else: raise Exception( f"Unknown kind of Boolean operator: {ast.op.Name}" ) return sc.result return TypedExpression(self, convertBoolOp(), typeWrapper(bool), False) if ast.matches.BinOp: lhs = self.convert_expression_ast(ast.left) if lhs is None: return None rhs = self.convert_expression_ast(ast.right) if rhs is None: return None return lhs.convert_bin_op(ast.op, rhs) if ast.matches.UnaryOp: operand = self.convert_expression_ast(ast.operand) return operand.convert_unary_op(ast.op) if ast.matches.Subscript: assert ast.slice.matches.Index val = self.convert_expression_ast(ast.value) if val is None: return None index = self.convert_expression_ast(ast.slice.value) if index is None: return None return val.convert_getitem(index) if ast.matches.Call: lhs = self.convert_expression_ast(ast.func) if lhs is None: return None for a in ast.args: assert not a.matches.Starred, "not implemented yet" args = [] kwargs = {} for a in ast.args: args.append(self.convert_expression_ast(a)) if args[-1] is None: return None for keywordArg in ast.keywords: argname = keywordArg.arg kwargs[argname] = self.convert_expression_ast(keywordArg.value) if kwargs[argname] is None: return None return lhs.convert_call(args, kwargs) if ast.matches.Compare: assert len( ast.comparators) == 1, "multi-comparison not implemented yet" assert len(ast.ops) == 1 lhs = self.convert_expression_ast(ast.left) if lhs is None: return None r = self.convert_expression_ast(ast.comparators[0]) if r is None: return None return lhs.convert_bin_op(ast.ops[0], r) if ast.matches.Tuple: raise NotImplementedError("not implemented yet") if ast.matches.IfExp: test = self.convert_expression_ast(ast.test) if test is None: return None test = test.toBool() if test is None: return None with self.ifelse(test) as (true_block, false_block): with true_block: true_res = self.convert_expression_ast(ast.body) with false_block: false_res = self.conversion_exception(ast.orelse) if true_res.expr_type != false_res.expr_type: out_type = typeWrapper( OneOf(true_res.expr_type.typeRepresentation, false_res.expr_type.typeRepresentation)) else: out_type = true_res.expr_type out_slot = self.allocateUninitializedSlot(out_type) with true_block: true_res = true_res.convert_to_type(out_type) out_slot.convert_copy_initialize(true_res) self.markUninitializedSlotInitialized(out_slot) with false_block: false_res = false_res.convert_to_type(out_type) out_slot.convert_copy_initialize(false_res) self.markUninitializedSlotInitialized(out_slot) return out_slot raise ConversionException("can't handle python expression type %s" % ast._which)