<commit_before>#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 <NAME> <<EMAIL>>

__version__ = '0.2.3a'
__date__ = '2014-09-27'
__author__ = '<NAME> <<EMAIL>>'
__license__ = 'MIT'


import ast
import collections
import copy
import functools
import operator
import string

from .util import identity, noop, const, foldr, compose2 as compose, method_of
from .util import first_arg as get_self
from .expressions import is_bitor
from .operators import fy, xfx, xfy, yfx, make_token


__all__ = [
    'Indicator',
    'UnificationFailed',
    'Cut',
    'Wildcard',
    'Variable',
    'Relation',
    'Atom',
    'String',
    'Num',
    'List',
    'Nil',
    'NIL',
    'Implication',
    'Conjunction',
    'Disjunction',
    'Adjunction',
    'Conditional',
    'Addition',
    'Subtraction',
    'Multiplication',
    'Division',
    'FloorDivision',
    'Remainder',
    'Exponentiation',
    'Negation',
    'Positive',
    'Negative',
    'Builder',
]


def get_name(self):
    return self.name


is_wildcard_name = '_'.__eq__
is_variable_name = compose(
    operator.itemgetter(0),
    set(string.ascii_uppercase + '_').__contains__)


first_param = compose(operator.attrgetter('params'), operator.itemgetter(0))
second_param = compose(operator.attrgetter('params'), operator.itemgetter(1))


parenthesized = '({})'.format
comma_separated = compose(functools.partial(map, str), ', '.join)


def action_str(term):
    if term.actions:
        return '[{}]'.format(', '.join(a.__name__ for a in term.actions))
    else:
        return ''


Indicator = collections.namedtuple('Indicator', 'name arity')


@method_of(Indicator)
def __str__(self):
    return '{}/{}:'.format(*self)


class UnificationFailed(Exception):
    pass


class Cut(Exception):
    pass


class Wildcard:

    __slots__ = ()

    __call__ = noop
    __str__ = '_'.__str__
    __repr__ = __str__
    __deepcopy__ = get_self

    deref = property(identity)
    fresh = get_self

    unify = noop
    unify_variable = noop
    unify_structure = noop


WILDCARD = Wildcard()


class Variable(collections.Counter):

    __slots__ = 'env', 'name'

    def __init__(self, *, env, name):
        self.env = env
        self.name = name

    def __call__(self):
        return None if self.deref is self else self.deref()

    def __str__(self):
        if self.deref is self:
            name = self.name
            seen = {self}
            todo = self.keys() - seen
            while todo:
                variable = todo.pop()
                seen.add(variable)
                todo |= variable.keys() - seen
                if name > variable.name in self.env:
                    name = variable.name
            return name
        else:
            return str(self.deref)

    __repr__ = __str__
    __eq__ = object.__eq__
    __hash__ = object.__hash__

    def __deepcopy__(self, memo, deepcopy=copy.deepcopy):
        var = deepcopy(self.env, memo)(self.name)
        if self and not var:
            memo[id(self)] = var
            var.update((deepcopy(k, memo), v) for k, v in self.items())
        return var

    def fresh(self, env):
        return env(self.name)

    @property
    def deref(self):
        return self.env[self.name]

    @deref.setter
    def ref(self, target):
        self.env[self.name] = target

    def unify(self, other, trail):
        other.unify_variable(self, trail)

    def unify_variable(self, other, trail):
        self[other] += 1
        other[self] += 1
        @trail
        def rollback(self=self, other=other):
            if self[other] > 1:
                self[other] -= 1
                other[self] -= 1
            else:
                del self[other]
                del other[self]

    def unify_structure(self, structure, trail):
        variables = [self]
        self.ref = structure
        seen = {self}
        todo = self.keys() - seen
        while todo:
            variable = todo.pop()
            variable.ref = structure
            seen.add(variable)
            todo |= variable.keys() - seen
            variables.append(variable)
        @trail
        def rollback(variables=variables):
            for variable in variables:
                variable.ref = variable


class Structure:

    __slots__ = 'env', 'name', 'params', 'actions'

    deref = property(identity)

    @property
    def arity(self):
        return len(self.params)

    @property
    def indicator(self):
        return Indicator(self.name, len(self.params))

    def __init__(self, *, env, name, params=(), actions=()):
        self.env = env
        self.name = name
        self.params = params
        self.actions = list(actions)

    def __repr__(self):<commit_msg>Version 0.2.3a<commit_after>#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2014 <NAME> <<EMAIL>>

__version__ = '0.2.3a'
__date__ = '2014-09-27'
__author__ = '<NAME> <<EMAIL>>'
__license__ = 'MIT'


import ast
import collections
import copy
import functools
import operator
import string

from .util import identity, noop, const, foldr, compose2 as compose, method_of
from .util import first_arg as get_self
from .expressions import is_bitor
from .operators import fy, xfx, xfy, yfx, make_token


__all__ = [
    'Indicator',
    'UnificationFailed',
    'Cut',
    'Wildcard',
    'Variable',
    'Relation',
    'Atom',
    'String',
    'Num',
    'List',
    'Nil',
    'NIL',
    'Implication',
    'Conjunction',
    'Disjunction',
    'Adjunction',
    'Conditional',
    'Addition',
    'Subtraction',
    'Multiplication',
    'Division',
    'FloorDivision',
    'Remainder',
    'Exponentiation',
    'Negation',
    'Positive',
    'Negative',
    'Builder',
]


def get_name(self):
    return self.name


is_wildcard_name = '_'.__eq__
is_variable_name = compose(
    operator.itemgetter(0),
    set(string.ascii_uppercase + '_').__contains__)


first_param = compose(operator.attrgetter('params'), operator.itemgetter(0))
second_param = compose(operator.attrgetter('params'), operator.itemgetter(1))


parenthesized = '({})'.format
comma_separated = compose(functools.partial(map, str), ', '.join)


def action_str(term):
    if term.actions:
        return '[{}]'.format(', '.join(a.__name__ for a in term.actions))
    else:
        return ''


Indicator = collections.namedtuple('Indicator', 'name arity')


@method_of(Indicator)
def __str__(self):
    return '{}/{}:'.format(*self)


class UnificationFailed(Exception):
    pass


class Cut(Exception):
    pass


class Wildcard:

    __slots__ = ()

    __call__ = noop
    __str__ = '_'.__str__
    __repr__ = __str__
    __deepcopy__ = get_self

    deref = property(identity)
    fresh = get_self

    unify = noop
    unify_variable = noop
    unify_structure = noop


WILDCARD = Wildcard()


class Variable(collections.Counter):

    __slots__ = 'env', 'name'

    def __init__(self, *, env, name):
        self.env = env
        self.name = name

    def __call__(self):
        return None if self.deref is self else self.deref()

    def __str__(self):
        if self.deref is self:
            name = self.name
            seen = {self}
            todo = self.keys() - seen
            while todo:
                variable = todo.pop()
                seen.add(variable)
                todo |= variable.keys() - seen
                if name > variable.name in self.env:
                    name = variable.name
            return name
        else:
            return str(self.deref)

    __repr__ = __str__
    __eq__ = object.__eq__
    __hash__ = object.__hash__

    def __deepcopy__(self, memo, deepcopy=copy.deepcopy):
        var = deepcopy(self.env, memo)(self.name)
        if self and not var:
            memo[id(self)] = var
            var.update((deepcopy(k, memo), v) for k, v in self.items())
        return var

    def fresh(self, env):
        return env(self.name)

    @property
    def deref(self):
        return self.env[self.name]

    @deref.setter
    def ref(self, target):
        self.env[self.name] = target

    def unify(self, other, trail):
        other.unify_variable(self, trail)

    def unify_variable(self, other, trail):
        self[other] += 1
        other[self] += 1
        @trail
        def rollback(self=self, other=other):
            if self[other] > 1:
                self[other] -= 1
                other[self] -= 1
            else:
                del self[other]
                del other[self]

    def unify_structure(self, structure, trail):
        self.ref = structure
        variables = [self]
        seen = {self}
        todo = self.keys() - seen
        while todo:
            variable = todo.pop()
            variable.ref = structure
            variables.append(variable)
            seen.add(variable)
            todo |= variable.keys() - seen
        @trail
        def rollback(variables=variables):
            for variable in variables:
                variable.ref = variable


class Structure:

    __slots__ = 'env', 'name', 'params', 'actions'

    deref = property(identity)

    @property
    def arity(self):
        return len(self.params)

    @property
    def indicator(self):
        return Indicator(self.name, len(self.params))

    def __init__(self, *, env, name, params=(), actions=()):
        self.env = env
        self.name = name
        self.params = params
        self.actions = list(actions)

    def __repr__(self):
{'fraction_non_alphanumeric': 0.12292041962488079, 'fraction_numerical': 0.005828123344283141, 'mean_word_length': 2.223360655737705, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 19, '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': '3986631', 'n_tokens_mistral': 3094, 'n_tokens_neox': 2940, 'n_words': 726}