<commit_before>""" Aliases gather aliasing informations. """

from pythran.analyses.global_declarations import GlobalDeclarations
from pythran.intrinsic import Intrinsic, Class, UnboundValue
from pythran.passmanager import ModuleAnalysis
from pythran.syntax import PythranSyntaxError
from pythran.tables import functions, methods, MODULES
from pythran.unparse import Unparser
from pythran.conversion import demangle
import pythran.metadata as md

import gast as ast
from itertools import product
import sys

if sys.version_info.major == 2:
    import StringIO as io
else:
    import io


IntrinsicAliases = dict()


class ContainerOf(object):
    '''
    Represents a container of something

    We just know that if indexed by the integer value `index',
    we get `containee'
    '''
    UnknownIndex = float('nan')

    __slots__ = 'index', 'containee'

    cache = {}

    def __new__(cls, *args, **kwargs):
        # cache the creation of new objects, so that same keys give same id
        # thus great hashing
        key = tuple(args), tuple(kwargs.items())
        if key not in ContainerOf.cache:
            new_obj = super(ContainerOf, cls).__new__(cls)
            ContainerOf.cache[key] = new_obj
        return ContainerOf.cache[key]

    def __init__(self, containee, index=UnknownIndex):
        self.index = index
        self.containee = containee


def save_intrinsic_alias(module):
    """ Recursively save default aliases for pythonic functions. """
    for v in module.values():
        if isinstance(v, dict):  # Submodules case
            save_intrinsic_alias(v)
        else:
            IntrinsicAliases[v] = frozenset((v,))
            if isinstance(v, Class):
                save_intrinsic_alias(v.fields)

for module in MODULES.values():
    save_intrinsic_alias(module)


class Aliases(ModuleAnalysis):
    '''
    Gather aliasing informations across nodes

    As a result, each node from the module is associated to a set of node or
    Intrinsic to which it *may* alias to.
    '''

    RetId = '@'

    def __init__(self):
        self.result = dict()
        self.aliases = None
        ContainerOf.cache.clear()
        super(Aliases, self).__init__(GlobalDeclarations)

    @staticmethod
    def dump(result, filter=None):
        def pp(n):
            output = io.StringIO()
            Unparser(n, output)
            return output.getvalue().strip()

        if isinstance(result, dict):
            for k, v in result.items():
                if (filter is None) or isinstance(k, filter):
                    print('{} => {}'.format(pp(k), sorted(map(pp, v))))
        elif isinstance(result, (frozenset, set)):
            print(sorted(map(pp, result)))

    def expand_unknown(self, node):
        # should include built-ins too?
        unkowns = {UnboundValue}.union(self.global_declarations.values())
        return unkowns.union(node.args)

    def get_unbound_value_set(self):
        return {UnboundValue}

    @staticmethod
    def access_path(node):

        def rec(w, n):
            if isinstance(n, ast.Name):
                return w.get(demangle(n.id), n.id)
            elif isinstance(n, ast.Attribute):
                return rec(w, n.value)[demangle(n.attr)]
            elif isinstance(n, ast.FunctionDef):
                return node.name
            else:
                return node
        return rec(MODULES, node)

    # aliasing created by expressions
    def add(self, node, values=set()):
        if not values:  # no given target for the alias
            if isinstance(node, Intrinsic):
                values = {node}  # an Intrinsic always aliases to itself
            else:
                values = self.get_unbound_value_set()
        assert isinstance(values, (frozenset, set))<commit_msg>Simplify alias.add method call<commit_after>""" Aliases gather aliasing informations. """

from pythran.analyses.global_declarations import GlobalDeclarations
from pythran.intrinsic import Intrinsic, Class, UnboundValue
from pythran.passmanager import ModuleAnalysis
from pythran.syntax import PythranSyntaxError
from pythran.tables import functions, methods, MODULES
from pythran.unparse import Unparser
from pythran.conversion import demangle
import pythran.metadata as md

import gast as ast
from itertools import product
import sys

if sys.version_info.major == 2:
    import StringIO as io
else:
    import io


IntrinsicAliases = dict()


class ContainerOf(object):
    '''
    Represents a container of something

    We just know that if indexed by the integer value `index',
    we get `containee'
    '''
    UnknownIndex = float('nan')

    __slots__ = 'index', 'containee'

    cache = {}

    def __new__(cls, *args, **kwargs):
        # cache the creation of new objects, so that same keys give same id
        # thus great hashing
        key = tuple(args), tuple(kwargs.items())
        if key not in ContainerOf.cache:
            new_obj = super(ContainerOf, cls).__new__(cls)
            ContainerOf.cache[key] = new_obj
        return ContainerOf.cache[key]

    def __init__(self, containee, index=UnknownIndex):
        self.index = index
        self.containee = containee


def save_intrinsic_alias(module):
    """ Recursively save default aliases for pythonic functions. """
    for v in module.values():
        if isinstance(v, dict):  # Submodules case
            save_intrinsic_alias(v)
        else:
            IntrinsicAliases[v] = frozenset((v,))
            if isinstance(v, Class):
                save_intrinsic_alias(v.fields)

for module in MODULES.values():
    save_intrinsic_alias(module)


class Aliases(ModuleAnalysis):
    '''
    Gather aliasing informations across nodes

    As a result, each node from the module is associated to a set of node or
    Intrinsic to which it *may* alias to.
    '''

    RetId = '@'

    def __init__(self):
        self.result = dict()
        self.aliases = None
        ContainerOf.cache.clear()
        super(Aliases, self).__init__(GlobalDeclarations)

    @staticmethod
    def dump(result, filter=None):
        def pp(n):
            output = io.StringIO()
            Unparser(n, output)
            return output.getvalue().strip()

        if isinstance(result, dict):
            for k, v in result.items():
                if (filter is None) or isinstance(k, filter):
                    print('{} => {}'.format(pp(k), sorted(map(pp, v))))
        elif isinstance(result, (frozenset, set)):
            print(sorted(map(pp, result)))

    def expand_unknown(self, node):
        # should include built-ins too?
        unkowns = {UnboundValue}.union(self.global_declarations.values())
        return unkowns.union(node.args)

    def get_unbound_value_set(self):
        return {UnboundValue}

    @staticmethod
    def access_path(node):

        def rec(w, n):
            if isinstance(n, ast.Name):
                return w.get(demangle(n.id), n.id)
            elif isinstance(n, ast.Attribute):
                return rec(w, n.value)[demangle(n.attr)]
            elif isinstance(n, ast.FunctionDef):
                return node.name
            else:
                return node
        return rec(MODULES, node)

    # aliasing created by expressions
    def add(self, node, values=None):
        if values is None:  # no given target for the alias
            if isinstance(node, Intrinsic):
                values = {node}  # an Intrinsic always aliases to itself
            else:
                values = self.get_unbound_value_set()
{'fraction_non_alphanumeric': 0.09438232161874334, 'fraction_numerical': 0.00026624068157614486, 'mean_word_length': 2.4686057248384117, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7431920', 'n_tokens_mistral': 2189, 'n_tokens_neox': 2109, 'n_words': 639}