Пример #1
0
 def constant(self, x):
     if isinstance(x, bool):
         return TypedExpression(self, native_ast.const_bool_expr(x), bool,
                                False)
     if isinstance(x, int):
         return TypedExpression(self, native_ast.const_int_expr(x), int,
                                False)
     if isinstance(x, float):
         return TypedExpression(self, native_ast.const_float_expr(x), float,
                                False)
     assert False
Пример #2
0
 def isInitializedVarExpr(self, name):
     return TypedExpression(self,
                            native_ast.Expression.StackSlot(
                                name=name + ".isInitialized",
                                type=native_ast.Bool),
                            bool,
                            isReference=True)
Пример #3
0
            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
Пример #4
0
    def pushLet(self, type, expression, isReference):
        """Push an arbitrary expression onto the stack."""
        varname = self.functionContext.let_varname()

        self.intermediates.append(
            ExpressionIntermediate.Simple(name=varname, expr=expression)
            )

        return TypedExpression(self, native_ast.Expression.Variable(varname), type, isReference)
Пример #5
0
    def pushReference(self, type, expression):
        """Push a reference to an object that's guaranteed to be alive for the duration of the expression."""
        type = typeWrapper(type)

        varname = self.functionContext.let_varname()

        self.intermediates.append(
            ExpressionIntermediate.Simple(name=varname, expr=expression)
            )

        return TypedExpression(self, native_ast.Expression.Variable(varname), type, True)
    def convert_default_initialize(self, context, target):
        if isinstance(None, self.typeRepresentation):
            target.convert_copy_initialize(
                TypedExpression(context, self,
                                runtime_functions.get_pyobj_None.call(),
                                False))
            return

        context.pushException(
            TypeError, "Can't default-initialize %s" %
            self.typeRepresentation.__qualname__)
Пример #7
0
    def construct_starargs_around(self, res, star_args_name):
        args_type = self._varname_to_type[star_args_name]

        stararg_slot = self.named_var_expr(star_args_name)

        return (args_type.convert_initialize(self, stararg_slot, [
            TypedExpression(
                native_ast.Expression.Variable(".star_args.%s" % i),
                args_type.element_types[i][1])
            for i in range(len(args_type.element_types))
        ]).with_comment("initialize *args slot") + res)
Пример #8
0
    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)
Пример #9
0
    def pushPod(self, type, expression):
        """stash an expression that generates POD passed as a value"""
        type = typeWrapper(type)

        assert type.is_pod
        assert not type.is_pass_by_ref

        varname = self.functionContext.let_varname()

        self.intermediates.append(
            ExpressionIntermediate.Simple(name=varname, expr=expression)
            )

        return TypedExpression(self, native_ast.Expression.Variable(varname), type, False)
Пример #10
0
    def push(self, type, callback, wantsTeardown=True):
        """Allocate a stackvariable of type 'type' and pass it to 'callback' which should return
        a native_ast.Expression or TypedExpression(None) initializing it.
        """
        type = typeWrapper(type)

        if type.is_pod:
            wantsTeardown = False

        varname = self.functionContext.stack_varname()

        resExpr = TypedExpression(
            self,
            native_ast.Expression.StackSlot(name=varname, type=type.getNativeLayoutType()),
            type,
            True
            )

        expr = callback(resExpr)

        if expr is None:
            expr = native_ast.nullExpr

        if isinstance(expr, TypedExpression):
            assert expr.expr_type.typeRepresentation is NoneType(), expr.expr_type
            expr = expr.expr
        else:
            assert isinstance(expr, native_ast.Expression)

        self.intermediates.append(
            ExpressionIntermediate.StackSlot(
                name=varname,
                expr=expr if not wantsTeardown else expr >> native_ast.Expression.ActivatesTeardown(varname)
                )
            )

        if wantsTeardown:
            with self.subcontext() as sc:
                type.convert_destroy(self, resExpr)

            self.teardowns.append(
                native_ast.Teardown.ByTag(
                    tag=varname,
                    expr=sc.result
                    )
                )

        return resExpr
Пример #11
0
    def allocateUninitializedSlot(self, type):
        type = typeWrapper(type)

        varname = self.functionContext.stack_varname()

        resExpr = TypedExpression(
            self,
            native_ast.Expression.StackSlot(name=varname,
                                            type=type.getNativeLayoutType()),
            type, True)

        if not type.is_pod:
            with self.subcontext() as sc:
                type.convert_destroy(self, resExpr)

            self.teardowns.append(
                native_ast.Teardown.ByTag(tag=varname, expr=sc.result))

        return resExpr
Пример #12
0
    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)
Пример #13
0
    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)
Пример #14
0
def pythonObjectRepresentation(context, f):
    if f is len:
        return TypedExpression(context, native_ast.nullExpr, LenWrapper(), False)

    if f is range:
        return TypedExpression(context, native_ast.nullExpr, _RangeWrapper, False)

    if f is bytecount:
        return TypedExpression(context, native_ast.nullExpr, BytecountWrapper(), False)

    if f is None:
        return TypedExpression(
            context,
            native_ast.Expression.Constant(
                val=native_ast.Constant.Void()
            ),
            NoneWrapper(),
            False
        )
    if isinstance(f, bool):
        return TypedExpression(
            context,
            native_ast.Expression.Constant(
                val=native_ast.Constant.Int(val=f, bits=1, signed=False)
            ),
            BoolWrapper(),
            False
        )
    if isinstance(f, int):
        return TypedExpression(
            context,
            native_ast.Expression.Constant(
                val=native_ast.Constant.Int(val=f, bits=64, signed=True)
            ),
            Int64Wrapper(),
            False
        )
    if isinstance(f, float):
        return TypedExpression(
            context,
            native_ast.Expression.Constant(
                val=native_ast.Constant.Float(val=f, bits=64)
            ),
            Float64Wrapper(),
            False
        )
    if isinstance(f, str):
        return StringWrapper().constant(context, f)
    if isinstance(f, bytes):
        return BytesWrapper().constant(context, f)

    if isinstance(f, type(pythonObjectRepresentation)):
        return TypedExpression(
            context,
            native_ast.nullExpr,
            PythonFreeFunctionWrapper(f),
            False
        )

    if hasattr(f, '__typed_python_category__'):
        if f.__typed_python_category__ == "Function":
            return TypedExpression(
                context,
                native_ast.nullExpr,
                PythonTypedFunctionWrapper(f),
                False
            )

    if isinstance(f, type):
        return TypedExpression(context, native_ast.nullExpr, PythonTypeObjectWrapper(f), False)

    if isinstance(f, ModuleType):
        return TypedExpression(context, native_ast.nullExpr, ModuleWrapper(f), False)

    return TypedExpression(context, native_ast.nullExpr, PythonFreeObjectWrapper(f), False)
Пример #15
0
    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)
Пример #16
0
    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)
Пример #17
0
 def inputArg(self, type, name):
     return TypedExpression(self, native_ast.Expression.Variable(name), type, type.is_pass_by_ref)
Пример #18
0
    def pushVoid(self, t=None):
        if t is None:
            t = typeWrapper(type(None))

        assert t.is_empty, t
        return TypedExpression(self, native_ast.nullExpr, t, False)