<commit_before># -*- coding: utf-8 -*-

"""
Cartesian Product Algorithm. We consider types as sets of classes (Sum) and
infer using the cartesian product of the argument sets/types.

Note that promotion is handled through overloading, e.g.:

    @overload('α -> β -> γ')
    def __add__(self, other):
        return other.__radd__(self)

    @overload('α -> α -> β')
    def __add__(self, other):
        result = ... # Perform addition
        return result

    @overload('α -> β -> γ')
    def __radd__(self, other):
        type = promote(typeof(self), typeof(other))
        return convert(other, type) + convert(self, type)

These are implemented in a trait which can be implemented by a user-defined
type (like Int). If there is no more specific overload, __radd__ will do the
promotion, triggering either an error or a call to a real implementation.
"""

from __future__ import print_function, division, absolute_import
from pprint import pprint
import collections
from itertools import product

from numba2 import promote, typeof, parse, typejoin
from numba2.errors import InferError, error_context_phase
from numba2.types import Mono, Function, Pointer, bool_, void
from numba2.typing import resolve_simple, TypeVar, TypeConstructor
from numba2.functionwrapper import FunctionWrapper
from numba2.viz.prettyprint import debug_print
from numba2.errors import error_context
from .resolution import infer_call
from .. import opaque

import pykit.types
from pykit import ir
from pykit.utils import flatten

import networkx

#===------------------------------------------------------------------===
# Utils
#===------------------------------------------------------------------===

def copy_context(context):
    return dict((binding, set(type)) for binding, type in context.iteritems())

def view(G):
    import matplotlib.pyplot as plt
    networkx.draw(G)
    plt.show()

Method = TypeConstructor("Method", 2, [{'coercible': True}] * 2)
#Method = type(parse("Method[func, self]"))

#===------------------------------------------------------------------===
# Inference structures
#===------------------------------------------------------------------===

class Context(object):
    """
    Type inference context.

    Attributes
    ==========

        context: { Operation : set([Type]) }
            bindings, mapping Operations (variables) to types (sets)

        graph: networkx.DiGraph
            constraint graph

        constraints: { Node : str }
            constraints for the nodes in the constraint graph

        metadata: { Node : dict }
            extra metadata for graph nodes in the constraint graph

    Only 'context' is mutable after construction!
    """

    def __init__(self, func, context, constraints, graph, metadata):
        self.func = func
        self.context = context
        self.constraints = constraints
        self.graph = graph
        self.metadata = metadata

    def copy(self):
        return Context(self.func, copy_context(self.context),
                       self.constraints, self.graph, self.metadata)

#===------------------------------------------------------------------===
# Inference
#===------------------------------------------------------------------===

def run(func, env):
    with error_context_phase(env, "Type inference"):
        cache = env['numba.inference.cache']
        argtypes = env['numba.typing.argtypes']
        ctx, signature = infer(cache, func, env, argtypes)

        env['numba.typing.signature'] = signature
        env['numba.typing.context'] = ctx.context
        env['numba.typing.constraints'] = ctx.constraints

        if debug_print(func, env):
            print(("Type context %s:" % (env['numba.state.func_name'],)).center(90))
            for op, typeset in ctx.context.iteritems():
                print("%s%15s = %s" % (" " * 30, op, typeset))
            pprint(ctx.context, indent=30)

        return ctx.func, env

def infer(cache, func, env, argtypes):
    """Infer types for the given function"""
    argtypes = tuple(argtypes)

    # -------------------------------------------------
    # Check cache

    cached = cache.lookup(func, argtypes)
    if cached:
        return cached

    # -------------------------------------------------
    # Infer<commit_msg>Don't fail when context cannot be printed<commit_after># -*- coding: utf-8 -*-

"""
Cartesian Product Algorithm. We consider types as sets of classes (Sum) and
infer using the cartesian product of the argument sets/types.

Note that promotion is handled through overloading, e.g.:

    @overload('α -> β -> γ')
    def __add__(self, other):
        return other.__radd__(self)

    @overload('α -> α -> β')
    def __add__(self, other):
        result = ... # Perform addition
        return result

    @overload('α -> β -> γ')
    def __radd__(self, other):
        type = promote(typeof(self), typeof(other))
        return convert(other, type) + convert(self, type)

These are implemented in a trait which can be implemented by a user-defined
type (like Int). If there is no more specific overload, __radd__ will do the
promotion, triggering either an error or a call to a real implementation.
"""

from __future__ import print_function, division, absolute_import
from pprint import pprint
import collections
from itertools import product

from numba2 import promote, typeof, parse, typejoin
from numba2.errors import InferError, error_context_phase
from numba2.types import Mono, Function, Pointer, bool_, void
from numba2.typing import resolve_simple, TypeVar, TypeConstructor
from numba2.functionwrapper import FunctionWrapper
from numba2.viz.prettyprint import debug_print
from numba2.errors import error_context
from .resolution import infer_call
from .. import opaque

import pykit.types
from pykit import ir
from pykit.utils import flatten

import networkx

#===------------------------------------------------------------------===
# Utils
#===------------------------------------------------------------------===

def copy_context(context):
    return dict((binding, set(type)) for binding, type in context.iteritems())

def view(G):
    import matplotlib.pyplot as plt
    networkx.draw(G)
    plt.show()

Method = TypeConstructor("Method", 2, [{'coercible': True}] * 2)
#Method = type(parse("Method[func, self]"))

#===------------------------------------------------------------------===
# Inference structures
#===------------------------------------------------------------------===

class Context(object):
    """
    Type inference context.

    Attributes
    ==========

        context: { Operation : set([Type]) }
            bindings, mapping Operations (variables) to types (sets)

        graph: networkx.DiGraph
            constraint graph

        constraints: { Node : str }
            constraints for the nodes in the constraint graph

        metadata: { Node : dict }
            extra metadata for graph nodes in the constraint graph

    Only 'context' is mutable after construction!
    """

    def __init__(self, func, context, constraints, graph, metadata):
        self.func = func
        self.context = context
        self.constraints = constraints
        self.graph = graph
        self.metadata = metadata

    def copy(self):
        return Context(self.func, copy_context(self.context),
                       self.constraints, self.graph, self.metadata)

#===------------------------------------------------------------------===
# Inference
#===------------------------------------------------------------------===

def run(func, env):
    with error_context_phase(env, "Type inference"):
        cache = env['numba.inference.cache']
        argtypes = env['numba.typing.argtypes']
        ctx, signature = infer(cache, func, env, argtypes)

        env['numba.typing.signature'] = signature
        env['numba.typing.context'] = ctx.context
        env['numba.typing.constraints'] = ctx.constraints

        if debug_print(func, env):
            print(("Type context %s:" % (env['numba.state.func_name'],)).center(90))
            for op, typeset in ctx.context.iteritems():
                print("%s%15s = %s" % (" " * 30, op, typeset))
            try:
                pprint(ctx.context, indent=30)
            except ValueError:
                print("unable to print context :((")

        return ctx.func, env

def infer(cache, func, env, argtypes):
    """Infer types for the given function"""
    argtypes = tuple(argtypes)

    # -------------------------------------------------
    # Check cache

    cached = cache.lookup(func, argtypes)
    if cached:
        return cached

    # -------------------------------------------------
    # Infer
{'fraction_non_alphanumeric': 0.21356986522290058, 'fraction_numerical': 0.004146987674231079, 'mean_word_length': 1.9641515875725504, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, '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': '3850456', 'n_tokens_mistral': 2249, 'n_tokens_neox': 2181, 'n_words': 713}