<commit_before>from __future__ import absolute_import
from .. import llvm


_KIND_CASTS = {

    # Integer -- Floating
    (llvm.FloatTypeKind, llvm.IntegerTypeKind): llvm.FPToSI,
    (llvm.DoubleTypeKind, llvm.IntegerTypeKind): llvm.FPToSI,
    (llvm.IntegerTypeKind, llvm.DoubleTypeKind): llvm.SIToFP,
    (llvm.IntegerTypeKind, llvm.FloatTypeKind): llvm.SIToFP,

    # Float -- Double
    (llvm.FloatTypeKind, llvm.DoubleTypeKind): llvm.FPExt,
    (llvm.DoubleTypeKind, llvm.FloatTypeKind): llvm.FPTrunc,

}


def value_emitter(func):
    """Marks a function as one which emits LLVM value as its result."""
    func.__n2o_emitter__ = True
    return func


@value_emitter
class IntrinsicEmitter(object):
    """Convenicnce emitter for wrapping ``llvm.{name}`` intrinsic functions.

    The *spec* lists types that are used to select particular
    overloaded variant.

    """

    def __init__(self, name, args, spec):
        self.name = name
        self.args = (llvm.ValueRef * len(args))(*args)
        self.spec = (llvm.TypeRef * len(spec))(*(t.llvm_type for t in spec))

    def __call__(self, builder):
        func = llvm.get_intrinsic(builder, self.name, self.spec)
        return llvm.BuildCall(builder, func, self.args, len(self.args), "call"), None


def cast(value, target_type):
    """Casts *value* to a specified *target_type*."""

    @value_emitter
    def emit(builder):
        # TODO support
        # * unsigned integers

        # No-op if type is the same
        value_type = llvm.TypeOf(value)
        if llvm.types_equal(target_type.llvm_type, value_type):
            return value, None

        value_kind = llvm.GetTypeKind(value_type)
        target_kind = llvm.GetTypeKind(target_type.llvm_type)

        def build_cast(op):
            return llvm.BuildCast(builder, op, value, target_type.llvm_type, "cast"), None

        if len(set((value_kind, target_kind))) == 2:
            try:
                # Casting between two different kinds of types
                return build_cast(_KIND_CASTS[(value_kind, target_kind)])
            except KeyError:
                raise TypeError("Cannot cast {0} to {1}".format(value, target_type))

        elif target_kind == llvm.IntegerTypeKind:
            # Same kind, but different(?) integer width
            value_width = llvm.GetIntTypeWidth(value_type)
            target_width = llvm.GetIntTypeWidth(target_type.llvm_type)

            if target_width > value_width:
                return build_cast(llvm.ZExt)
            elif target_width < value_width:
                return build_cast(llvm.Trunc)
            else:
                return value, None

        else:
            raise TypeError("Cannot cast {0} to {1}".format(value, target_type))

    return emit


def range_(*args):
    """``range([start,] stop[, step])``

    Returns (start, stop, step) LLVM value tuple which is then can be used
    by the compiler to emit the ``for`` loop code.

    """

    @value_emitter
    def emit(builder):<commit_msg>Return proper type with cast() result<commit_after>from __future__ import absolute_import
from .. import llvm


_KIND_CASTS = {

    # Integer -- Floating
    (llvm.FloatTypeKind, llvm.IntegerTypeKind): llvm.FPToSI,
    (llvm.DoubleTypeKind, llvm.IntegerTypeKind): llvm.FPToSI,
    (llvm.IntegerTypeKind, llvm.DoubleTypeKind): llvm.SIToFP,
    (llvm.IntegerTypeKind, llvm.FloatTypeKind): llvm.SIToFP,

    # Float -- Double
    (llvm.FloatTypeKind, llvm.DoubleTypeKind): llvm.FPExt,
    (llvm.DoubleTypeKind, llvm.FloatTypeKind): llvm.FPTrunc,

}


def value_emitter(func):
    """Marks a function as one which emits LLVM value as its result."""
    func.__n2o_emitter__ = True
    return func


@value_emitter
class IntrinsicEmitter(object):
    """Convenicnce emitter for wrapping ``llvm.{name}`` intrinsic functions.

    The *spec* lists types that are used to select particular
    overloaded variant.

    """

    def __init__(self, name, args, spec):
        self.name = name
        self.args = (llvm.ValueRef * len(args))(*args)
        self.spec = (llvm.TypeRef * len(spec))(*(t.llvm_type for t in spec))

    def __call__(self, builder):
        func = llvm.get_intrinsic(builder, self.name, self.spec)
        return llvm.BuildCall(builder, func, self.args, len(self.args), "call"), None


def cast(value, target_type):
    """Casts *value* to a specified *target_type*."""

    @value_emitter
    def emit(builder):

        # No-op if LLVM type is the same
        value_type = llvm.TypeOf(value)
        if llvm.types_equal(target_type.llvm_type, value_type):
            return value, target_type

        value_kind = llvm.GetTypeKind(value_type)
        target_kind = llvm.GetTypeKind(target_type.llvm_type)

        def build_cast(op):
            return llvm.BuildCast(builder, op, value, target_type.llvm_type, "cast"), target_type

        if len(set((value_kind, target_kind))) == 2:
            try:
                # Casting between two different kinds of types
                return build_cast(_KIND_CASTS[(value_kind, target_kind)])
            except KeyError:
                raise TypeError("Cannot cast {0} to {1}".format(value, target_type))

        elif target_kind == llvm.IntegerTypeKind:
            # Same kind, but different(?) integer width
            value_width = llvm.GetIntTypeWidth(value_type)
            target_width = llvm.GetIntTypeWidth(target_type.llvm_type)

            if target_width > value_width:
                return build_cast(llvm.ZExt)
            elif target_width < value_width:
                return build_cast(llvm.Trunc)
            else:
                return value, target_type

        else:
            raise TypeError("Cannot cast {0} to {1}".format(value, target_type))

    return emit


def range_(*args):
    """``range([start,] stop[, step])``

    Returns (start, stop, step) LLVM value tuple which is then can be used
    by the compiler to emit the ``for`` loop code.

    """

    @value_emitter
    def emit(builder):
{'fraction_non_alphanumeric': 0.10693497422251788, 'fraction_numerical': 0.0019956760352569432, 'mean_word_length': 2.7077681874229347, 'pattern_counts': {'":': 0, '<': 5, '<?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': '3271966', 'n_tokens_mistral': 1853, 'n_tokens_neox': 1817, 'n_words': 471}