예제 #1
0
파일: types.py 프로젝트: yws/pythran
    def visit_FunctionDef(self, node):
        self.curr_locals_declaration = self.passmanager.gather(
            LocalNodeDeclarations, node)
        self.current = node
        self.typedefs = list()
        self.name_to_nodes = {arg.id: {arg} for arg in node.args.args}
        self.yield_points = self.passmanager.gather(YieldPoints, node)

        # two stages, one for inter procedural propagation
        self.stage = 0
        self.generic_visit(node)

        # and one for backward propagation
        # but this step is generally costly
        if cfg.getboolean('typing', 'enable_two_steps_typing'):
            self.stage = 1
            self.generic_visit(node)

        # propagate type information through all aliases
        for name, nodes in self.name_to_nodes.items():
            final_node = ast.Name("__fake__" + name, ast.Load(), None)
            for n in nodes:
                self.combine(final_node, n)
            for n in nodes:
                self.result[n] = self.result[final_node]
        self.current_global_declarations[node.name] = node
        # return type may be unset if the function always raises
        return_type = self.result.get(node,
                                      NamedType("pythonic::types::none_type"))

        self.result[node] = (Returnable(return_type), self.typedefs)
        for k in self.passmanager.gather(LocalNodeDeclarations, node):
            self.result[k] = self.get_qualifier(k)(self.result[k])
예제 #2
0
파일: types.py 프로젝트: LuisBL/pythran
 def visit_Name(self, node):
     if node.id in self.name_to_nodes:
         for n in self.name_to_nodes[node.id]:
             self.combine(node, n)
     elif node.id in self.current_global_declarations:
         self.combine(node, self.current_global_declarations[node.id])
     else:
         self.result[node] = NamedType(node.id, {Weak})
예제 #3
0
파일: types.py 프로젝트: LuisBL/pythran
 def visit_Set(self, node):
     """ Define set type from all elements type (or empty_set type). """
     self.generic_visit(node)
     if node.elts:
         for elt in node.elts:
             self.combine(node, elt, unary_op=SetType)
     else:
         self.result[node] = NamedType("pythonic::types::empty_set")
예제 #4
0
    def visit_Assign(self, node):
        """
        Create Assign node for final Cxx representation.

        It tries to handle multi assignment like:

        >> a = b = c = 2

        If only one local variable is assigned, typing is added:

        >> int a = 2;

        TODO: Handle case of multi-assignement for some local variables.

        Finally, process OpenMP clause like #pragma omp atomic
        """
        if not all(isinstance(n, (ast.Name, ast.Subscript))
                   for n in node.targets):
            raise PythranSyntaxError(
                "Must assign to an identifier or a subscript",
                node)
        value = self.visit(node.value)
        targets = [self.visit(t) for t in node.targets]
        alltargets = "= ".join(targets)
        islocal = (len(targets) == 1 and
                   isinstance(node.targets[0], ast.Name) and
                   node.targets[0].id in self.scope[node])
        if islocal and not self.yields:
            # remove this decl from local decls
            tdecls = {t.id for t in node.targets}
            self.ldecls = {d for d in self.ldecls if d.id not in tdecls}
            # add a local declaration
            if self.types[node.targets[0]].iscombined():
                alltargets = '{} {}'.format(self.typeof(node.targets[0]),
                                            alltargets)
            elif isinstance(self.types[node.targets[0]], Assignable):
                alltargets = '{} {}'.format(
                    Assignable(NamedType('decltype({})'.format(value))),
                    alltargets)
            else:
                assert isinstance(self.types[node.targets[0]], Lazy)
                alltargets = '{} {}'.format(
                    Lazy(NamedType('decltype({})'.format(value))),
                    alltargets)
        stmt = Assign(alltargets, value)
        return self.process_omp_attachements(node, stmt)
예제 #5
0
파일: types.py 프로젝트: LuisBL/pythran
 def __init__(self):
     self.result = dict()
     self.result["bool"] = NamedType("bool")
     self.combiners = defaultdict(UserFunction)
     self.current_global_declarations = dict()
     self.max_recompute = 1  # max number of use to be lazy
     ModuleAnalysis.__init__(self, StrictAliases, LazynessAnalysis)
     self.curr_locals_declaration = None
예제 #6
0
파일: types.py 프로젝트: LuisBL/pythran
    def visit_Num(self, node):
        """
        Set type for number.

        It could be int, long or float so we use the default python to pythonic
        type converter.
        """
        self.result[node] = NamedType(PYTYPE_TO_CTYPE_TABLE[type(node.n)])
예제 #7
0
def fill_constants_types(module_name, elements):
    """ Recursively save arguments name and default value. """
    for elem, intrinsic in elements.items():
        if isinstance(intrinsic, dict):  # Submodule case
            fill_constants_types(module_name + (elem, ), intrinsic)
        elif isinstance(intrinsic, ConstantIntr):
            # use introspection to get the Python constants types
            cst = getattr(__import__(".".join(module_name)), elem)
            intrinsic.return_type = NamedType(PYTYPE_TO_CTYPE_TABLE[type(cst)])
예제 #8
0
파일: types.py 프로젝트: yws/pythran
 def visit_Attribute(self, node):
     """ Compute typing for an attribute node. """
     obj, path = attr_to_path(node)
     # If no type is given, use a decltype
     if obj.isliteral():
         typename = pytype_to_ctype(obj.signature)
         self.result[node] = NamedType(typename)
     else:
         self.result[node] = DeclType('::'.join(path) + '{}')
예제 #9
0
파일: types.py 프로젝트: yws/pythran
    def visit_Num(self, node):
        """
        Set type for number.

        It could be int, long or float so we use the default python to pythonic
        type converter.
        """
        ty = type(node.n)
        self.result[node] = NamedType(pytype_to_ctype(ty))
예제 #10
0
파일: types.py 프로젝트: yang123vc/pythran
 def visit_ExceptHandler(self, node):
     if node.type and node.name:
         if not isinstance(node.type, ast.Tuple):
             tname = NamedType(
                 'pythonic::types::{0}'.format(node.type.attr))
             self.result[node.type] = tname
             self.combine(node.name, node.type, aliasing_type=True,
                          register=True)
     list(map(self.visit, node.body))
예제 #11
0
파일: types.py 프로젝트: yang123vc/pythran
 def visit_Dict(self, node):
     """ Define set type from all elements type (or empty_dict type). """
     self.generic_visit(node)
     if node.keys:
         for key, value in zip(node.keys, node.values):
             value_type = self.result[value]
             self.combine(node, key,
                          unary_op=partial(DictType, of_value=value_type))
     else:
         self.result[node] = NamedType("pythonic::types::empty_dict")
예제 #12
0
파일: types.py 프로젝트: yws/pythran
 def visit_Name(self, node):
     if node.id in self.name_to_nodes:
         for n in self.name_to_nodes[node.id]:
             self.combine(node, n)
     elif node.id in self.current_global_declarations:
         newtype = NamedType(self.current_global_declarations[node.id].name)
         if node not in self.result:
             self.result[node] = newtype
     else:
         self.result[node] = UnknownType
예제 #13
0
파일: backend.py 프로젝트: gouarin/pythran
    def gen_for(self, node, target, local_iter, local_iter_decl, loop_body):
        """
        Create For representation on iterator for Cxx generation.

        Examples
        --------
        >> "omp parallel for"
        >> for i in xrange(10):
        >>     ... do things ...

        Becomes

        >> "omp parallel for shared(__iterX)"
        >> for(decltype(__iterX)::iterator __targetX = __iterX.begin();
               __targetX < __iterX.end(); ++__targetX)
        >>         typename decltype(__targetX)::reference i = *__targetX;
        >>     ... do things ...

        It the case of not local variable, typing for `i` disappear and typing
        is removed for iterator in case of yields statement in function.
        """
        # Choose target variable for iterator (which is iterator type)
        local_target = "__target{0}".format(len(self.break_handlers))
        local_target_decl = NamedType(
            "typename decltype({0})::iterator".format(local_iter))

        # For yield function, all variables are globals.
        if self.yields:
            self.extra_declarations.append((
                local_target,
                local_target_decl,
            ))
            local_target_decl = ""

        # If variable is local to the for body it's a ref to the iterator value
        # type
        if node.target.id in self.scope[node] and not self.yields:
            self.ldecls = {d for d in self.ldecls if d.id != node.target.id}
            local_type = "typename decltype({})::reference ".format(
                local_target)
        else:
            local_type = ""

        # Assign iterable value
        loop_body_prelude = Statement("{} {}= *{}".format(
            local_type, target, local_target))

        # Create the loop
        loop = For(
            "{0} {1} = {2}.begin()".format(local_target_decl, local_target,
                                           local_iter),
            "{0} < {1}.end()".format(local_target,
                                     local_iter), "++{0}".format(local_target),
            Block([loop_body_prelude, loop_body]))
        return [self.process_omp_attachements(node, loop)]
예제 #14
0
파일: types.py 프로젝트: LuisBL/pythran
 def register(name, module):
     """ Recursively save function typing and combiners for Pythonic."""
     for fname, function in module.iteritems():
         if isinstance(function, dict):
             register(name + "::" + fname, function)
         else:
             tname = 'pythonic::{0}::functor::{1}'.format(name, fname)
             self.result[function] = NamedType(tname)
             self.combiners[function] = function
             if isinstance(function, Class):
                 register(name + "::" + fname, function.fields)
예제 #15
0
    def gen_for(self, node, target, local_iter, loop_body):
        """
        Create For representation on iterator for Cxx generation.

        Examples
        --------
        >> "omp parallel for"
        >> for i in xrange(10):
        >>     ... do things ...

        Becomes

        >> "omp parallel for shared(__iterX)"
        >> for(decltype(__iterX)::iterator __targetX = __iterX.begin();
               __targetX < __iterX.end(); ++__targetX)
        >>         auto&& i = *__targetX;
        >>     ... do things ...

        It the case of not local variable, typing for `i` disappear and typing
        is removed for iterator in case of yields statement in function.
        """
        # Choose target variable for iterator (which is iterator type)
        local_target = "__target{0}".format(len(self.break_handlers))
        local_target_decl = NamedType(
            "typename decltype({0})::iterator".format(local_iter))

        # If variable is local to the for body it's a ref to the iterator value
        # type
        if node.target.id in self.scope[node] and not hasattr(self, 'yields'):
            self.ldecls.remove(node.target.id)
            local_type = "auto&&"
        else:
            local_type = ""

        # Assign iterable value
        loop_body_prelude = Statement("{} {}= *{}".format(
            local_type, target, local_target))

        # Create the loop
        assign = self.make_assign(local_target_decl, local_target, local_iter)
        loop = For("{}.begin()".format(assign),
                   "{0} < {1}.end()".format(local_target, local_iter),
                   "++{0}".format(local_target),
                   Block([loop_body_prelude, loop_body]))
        return [self.process_omp_attachements(node, loop)]
예제 #16
0
파일: types.py 프로젝트: yws/pythran
 def visit_Str(self, node):
     """ Set the pythonic string type. """
     self.result[node] = NamedType(pytype_to_ctype(str))
예제 #17
0
파일: types.py 프로젝트: LuisBL/pythran
    def combine_(self, node, othernode, op, unary_op, register):
        try:
            if register:  # this comes from an assignment,
                # so we must check where the value is assigned
                node_id, depth = self.node_to_id(node)
                if depth > 0:
                    node = ast.Name(node_id, ast.Load())
                self.name_to_nodes.setdefault(node_id, set()).add(node)

                former_unary_op = unary_op

                # update the type to reflect container nesting
                def unary_op(x):
                    return reduce(lambda t, n: ContainerType(t), xrange(depth),
                                  former_unary_op(x))

            if isinstance(othernode, ast.FunctionDef):
                new_type = NamedType(othernode.name)
                if node not in self.result:
                    self.result[node] = new_type
            else:
                # only perform inter procedural combination upon stage 0
                if register and self.isargument(node) and self.stage == 0:
                    node_id, _ = self.node_to_id(node)
                    if node not in self.result:
                        self.result[node] = unary_op(self.result[othernode])
                    assert self.result[node], "found an alias with a type"

                    parametric_type = PType(self.current,
                                            self.result[othernode])
                    if self.register(parametric_type):

                        current_function = self.combiners[self.current]

                        def translator_generator(args, op, unary_op):
                            ''' capture args for translator generation'''
                            def interprocedural_type_translator(s, n):
                                translated_othernode = ast.Name(
                                    '__fake__', ast.Load())
                                s.result[translated_othernode] = (
                                    parametric_type.instanciate(
                                        s.current,
                                        [s.result[arg] for arg in n.args]))
                                # look for modified argument
                                for p, effective_arg in enumerate(n.args):
                                    formal_arg = args[p]
                                    if formal_arg.id == node_id:
                                        translated_node = effective_arg
                                        break
                                try:
                                    s.combine(translated_node,
                                              translated_othernode,
                                              op,
                                              unary_op,
                                              register=True,
                                              aliasing_type=True)
                                except NotImplementedError:
                                    pass
                                    # this may fail when the effective
                                    # parameter is an expression
                                except UnboundLocalError:
                                    pass
                                    # this may fail when translated_node
                                    # is a default parameter

                            return interprocedural_type_translator

                        translator = translator_generator(
                            self.current.args.args, op,
                            unary_op)  # deferred combination
                        current_function.add_combiner(translator)
                else:
                    new_type = unary_op(self.result[othernode])
                    if node not in self.result:
                        self.result[node] = new_type
                    else:
                        self.result[node] = op(self.result[node], new_type)
        except UnboundableRValue:
            pass
예제 #18
0
     MethodIntr(update_effects),
     "difference":
     ConstMethodIntr(),
     "difference_update":
     MethodIntr(update_effects),
     "symmetric_difference":
     ConstMethodIntr(),
     "symmetric_difference_update":
     MethodIntr(update_effects),
     "issuperset":
     ConstMethodIntr(return_range=prange.bool_values),
     "issubset":
     ConstMethodIntr(return_range=prange.bool_values),
 },
 "Exception": {
     "args": AttributeIntr(return_type=NamedType("pythonic::types::str")),
     "errno": AttributeIntr(return_type=NamedType("pythonic::types::str")),
     "strerror":
     AttributeIntr(return_type=NamedType("pythonic::types::str")),
     "filename":
     AttributeIntr(return_type=NamedType("pythonic::types::str")),
 },
 "float": {
     "is_integer": ConstMethodIntr(return_range=prange.bool_values),
 },
 "complex": {
     "conjugate": ConstMethodIntr(),
     "real": AttributeIntr(return_type=NamedType("double")),
     "imag": AttributeIntr(return_type=NamedType("double")),
 },
 "dict": {
예제 #19
0
파일: types.py 프로젝트: LuisBL/pythran
 def visit_Str(self, node):
     """ Set the pythonic string type. """
     self.result[node] = NamedType(PYTYPE_TO_CTYPE_TABLE[str])