File size: 2,001 Bytes
c65f48d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
from collections import defaultdict


class DuplicatedNameError(NameError):
    pass


class NameScope(object):
    def __init__(self):
        self._useset = set([''])
        self._basenamemap = defaultdict(int)

    def is_used(self, name):
        return name in self._useset

    def register(self, name, deduplicate=False):
        if deduplicate:
            name = self.deduplicate(name)
        elif self.is_used(name):
            raise DuplicatedNameError(name)
        self._useset.add(name)
        return name

    def deduplicate(self, name):
        basename = name
        while self.is_used(name):
            ident = self._basenamemap[basename] + 1
            self._basenamemap[basename] = ident
            name = "{0}.{1}".format(basename, ident)
        return name

    def get_child(self):
        return type(self)(parent=self)


class _StrCaching(object):

    def _clear_string_cache(self):
        try:
            del self.__cached_str
        except AttributeError:
            pass

    def __str__(self):
        try:
            return self.__cached_str
        except AttributeError:
            s = self.__cached_str = self._to_string()
            return s


class _StringReferenceCaching(object):

    def get_reference(self):
        try:
            return self.__cached_refstr
        except AttributeError:
            s = self.__cached_refstr = self._get_reference()
            return s


class _HasMetadata(object):

    def set_metadata(self, name, node):
        """
        Attach unnamed metadata *node* to the metadata slot *name* of this
        value.
        """
        self.metadata[name] = node

    def _stringify_metadata(self, leading_comma=False):
        if self.metadata:
            buf = []
            if leading_comma:
                buf.append("")
            buf += ["!{0} {1}".format(k, v.get_reference())
                    for k, v in self.metadata.items()]
            return ', '.join(buf)
        else:
            return ''