コード例 #1
0
 def __init__(self, subs=Map()):
     if isinstance(subs, dict):
         self.subs = Map()
         for k, v in subs.items():
             self.subs = self.subs.insert(k, v)
     else:
         self.subs = subs
コード例 #2
0
def test_map_iterates_over_all_association():
    items = {("one", 1), ("two", 2)}
    mapping = Map()
    for key, value in items:
        mapping = mapping.insert(key, value)
    mapping_iter = iter(mapping)
    assert set(mapping_iter) == items
コード例 #3
0
def test_map_insert_does_not_modify_old_map():
    mapping1 = Map().insert("one", 1)
    mapping1_backup = copy.deepcopy(mapping1)

    mapping2 = mapping1.insert("two", 2)
    assert mapping2 is not mapping1

    items_a = set(mapping1)
    items_b = set(mapping1_backup)
    assert items_a == items_b
コード例 #4
0
def test_remove_item():
    mapping0 = Map()
    mapping1 = mapping0.insert("one", 1)
    mapping2 = mapping1.insert("two", 2)
    mapping3 = mapping2.insert("three", 3)

    mapping = mapping3.remove("two")

    assert set(mapping) == {("one", 1), ("three", 3)}
    assert set(mapping3) == {("one", 1), ("two", 2), ("three", 3)}
    assert set(mapping2) == {("one", 1), ("two", 2)}
    assert set(mapping1) == {("one", 1)}
    assert set(mapping0) == set()
コード例 #5
0
def test_map_deepcopy_returns_different_object_with_same_items():
    map0 = Map().insert("key", "value")
    map1 = copy.deepcopy(map0)
    assert map0 is not map1

    items_a = set(map0)
    items_b = set(map1)
    assert items_a == items_b
コード例 #6
0
def test_all_empty_maps_share_an_instance():
    assert Map() is Map()
コード例 #7
0
def test_empty_map_supports_iteration():
    assert list(Map()) == []
コード例 #8
0
def test_empty_mapping():
    assert Map().is_empty()
コード例 #9
0
def test_map_is_immutable():
    mapping = Map().insert("one", 1)
    with raises(TypeError):
        mapping.key = 0
    with raises(TypeError):
        mapping[0] = 0
コード例 #10
0
def test_can_look_up_a_value_after_inserting_another():
    mapping = Map()
    mapping = mapping.insert("one", 1)
    mapping = mapping.insert("two", 2)
    assert mapping.lookup("two") == 2
    assert mapping.lookup("one") == 1
コード例 #11
0
def test_looking_up_existing_key_returns_value():
    mapping = Map().insert("key", "value")
    val = mapping.lookup("key")
    assert val == "value"
コード例 #12
0
def test_looking_up_in_the_empty_map_raises():
    mapping = Map()
    with raises(KeyError):
        mapping.lookup("key")
コード例 #13
0
def test_empty_map_deepcopy_returns_same_object():
    map0 = Map()
    map1 = copy.deepcopy(map0)
    assert map0 is map1
コード例 #14
0
def test_map_insert_returns_map():
    mapping = Map().insert("key", "value")
    assert isinstance(mapping, Map)
コード例 #15
0
def test_remove_nonexisting_key_raises():
    mapping = Map().insert("key", "value")
    with raises(KeyError):
        mapping.remove("foo")
コード例 #16
0
def test_map_with_elements_inserted_is_not_empty():
    mapping = Map().insert("key", "value")
    assert not mapping.is_empty()
コード例 #17
0
def test_walk_deep_map():
    w, x, y, z = variables("w, x, y, z")
    sub = Substitution({x: "b", z: y, w: Map().insert(x, z).insert("a", "b")})
    value = sub.walk_deep(w)
    assert value == Map().insert("b", y).insert("a", "b")
コード例 #18
0
class Substitution:
    def __init__(self, subs=Map()):
        if isinstance(subs, dict):
            self.subs = Map()
            for k, v in subs.items():
                self.subs = self.subs.insert(k, v)
        else:
            self.subs = subs

    @staticmethod
    def is_valid():
        return True

    def walk(self, var):
        try:
            value = self.subs.lookup(var)
        except KeyError:
            return var
        return self.walk_var(value)

    def walk_var(self, value):
        if is_var(value):
            return self.walk(value)
        return value

    def walk_deep(self, x):
        x = self.walk_var(x)

        if is_var(x) or is_atom(x):
            return x

        if hasattr(x, '__map__'):
            return x.__map__(self.walk_deep)
        elif isinstance(x, (list, tuple, set)):
            return type(x)(self.walk_deep(item) for item in x)
        elif isinstance(x, dict):
            return {self.walk_deep(k): self.walk_deep(v) for k, v in x.items()}
        else:
            raise NotImplementedError("walk_deep: {}".format(type(x)))

    def extend(self, var, value):
        if self.occurs(var, value):
            return InvalidSubstitution()
        return Substitution(self.subs.insert(var, value))

    def occurs(self, var, value):
        value = self.walk_var(value)
        if is_var(value):
            return var == value
        elif is_atom(value):
            return False
        iterator = as_iterable(value)
        if iterator:
            return any(self.occurs(var, v) for v in iterator)
        return False

    def unify(self, x, y, strict=True):
        x = self.walk_var(x)
        y = self.walk_var(y)

        if x == y:
            return self
        elif hasattr(x, '__unify__'):
            return x.__unify__(y, self)
        elif hasattr(y, '__unify__'):
            return y.__unify__(x, self)
        elif is_atom(x) or is_atom(y):
            return InvalidSubstitution()

        if strict and type(x) != type(y):
            return InvalidSubstitution()

        if len(x) != len(y):
            return InvalidSubstitution()

        x_iter = as_iterable(x)
        y_iter = as_iterable(y)

        if x_iter and y_iter:
            for xi, yi in zip(x_iter, y_iter):
                self = self.unify(xi, yi)
            return self
        return InvalidSubstitution()

    def reify(self, v):
        v = self.walk_deep(v)
        r = Substitution()._reify(v)
        return r.walk_deep(v)

    def _reify(self, v):
        v = self.walk_var(v)
        if is_var(v):
            n = len(self.subs)
            rv = ReifiedVariable(n)
            return Substitution(self.subs.insert(v, rv))
        elif is_atom(v):
            return self

        r = self
        for item in as_iterable(v):
            r = r._reify(item)
        return r

    def __eq__(self, other):
        return isinstance(other, Substitution) and dict(self.subs) == dict(other.subs)

    def __hash__(self):
        return hash(self.subs)

    def __repr__(self):
        return 'Substitution({})'.format(self.subs)