paul@554 | 1 | #!/usr/bin/env python |
paul@554 | 2 | |
paul@554 | 3 | """ |
paul@554 | 4 | Fundamental program data structure abstractions. |
paul@554 | 5 | |
paul@554 | 6 | Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Paul Boddie <paul@boddie.org.uk> |
paul@554 | 7 | |
paul@554 | 8 | This program is free software; you can redistribute it and/or modify it under |
paul@554 | 9 | the terms of the GNU General Public License as published by the Free Software |
paul@554 | 10 | Foundation; either version 3 of the License, or (at your option) any later |
paul@554 | 11 | version. |
paul@554 | 12 | |
paul@554 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT |
paul@554 | 14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
paul@554 | 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
paul@554 | 16 | details. |
paul@554 | 17 | |
paul@554 | 18 | You should have received a copy of the GNU General Public License along with |
paul@554 | 19 | this program. If not, see <http://www.gnu.org/licenses/>. |
paul@554 | 20 | """ |
paul@554 | 21 | |
paul@554 | 22 | # Short representation display support. |
paul@554 | 23 | |
paul@554 | 24 | def shortrepr(obj): |
paul@554 | 25 | if obj is None: |
paul@554 | 26 | return repr(None) |
paul@554 | 27 | else: |
paul@554 | 28 | return obj.__shortrepr__() |
paul@554 | 29 | |
paul@554 | 30 | # Mix-ins and abstract classes. |
paul@554 | 31 | |
paul@554 | 32 | class Naming: |
paul@554 | 33 | |
paul@554 | 34 | "A mix-in providing naming conveniences." |
paul@554 | 35 | |
paul@554 | 36 | def full_name(self): |
paul@554 | 37 | if self.name is not None: |
paul@554 | 38 | return self.parent.full_name() + "." + self.name |
paul@554 | 39 | else: |
paul@554 | 40 | return self.parent.full_name() |
paul@554 | 41 | |
paul@612 | 42 | no_attributes = {} |
paul@612 | 43 | |
paul@609 | 44 | class Namespace: |
paul@609 | 45 | |
paul@609 | 46 | "A mix-in providing basic namespace functionality." |
paul@609 | 47 | |
paul@612 | 48 | def all_attributes(self): |
paul@609 | 49 | |
paul@609 | 50 | """ |
paul@612 | 51 | Return all attributes accessible through a namespace, whether provided |
paul@612 | 52 | directly by the namespace or by other mechanisms. |
paul@609 | 53 | """ |
paul@609 | 54 | |
paul@612 | 55 | return no_attributes |
paul@609 | 56 | |
paul@609 | 57 | class Constant: |
paul@609 | 58 | |
paul@609 | 59 | "A superclass for all constant or context-free structures." |
paul@609 | 60 | |
paul@609 | 61 | pass |
paul@609 | 62 | |
paul@554 | 63 | # Instances are special in that they need to be wrapped together with context in |
paul@554 | 64 | # a running program, but they are not generally constant. |
paul@554 | 65 | |
paul@609 | 66 | class Instance(Namespace): |
paul@554 | 67 | |
paul@554 | 68 | "A placeholder indicating the involvement of an instance." |
paul@554 | 69 | |
paul@554 | 70 | def __init__(self): |
paul@554 | 71 | self.parent = None |
paul@554 | 72 | |
paul@554 | 73 | # Image generation details. |
paul@554 | 74 | |
paul@554 | 75 | self.location = None |
paul@554 | 76 | |
paul@554 | 77 | def __repr__(self): |
paul@554 | 78 | return "<instance>" |
paul@554 | 79 | |
paul@554 | 80 | def __eq__(self, other): |
paul@554 | 81 | return other.__class__ is Instance |
paul@554 | 82 | |
paul@554 | 83 | def __ne__(self, other): |
paul@554 | 84 | return not self.__eq__(other) |
paul@554 | 85 | |
paul@554 | 86 | def __hash__(self): |
paul@554 | 87 | return 0 |
paul@554 | 88 | |
paul@554 | 89 | __shortrepr__ = __repr__ |
paul@554 | 90 | |
paul@554 | 91 | # Common instance construction. |
paul@554 | 92 | |
paul@554 | 93 | common_instance = Instance() |
paul@554 | 94 | |
paul@554 | 95 | def make_instance(): |
paul@554 | 96 | return common_instance |
paul@554 | 97 | |
paul@554 | 98 | # Data objects appearing in programs before run-time. |
paul@554 | 99 | |
paul@554 | 100 | class Const(Constant, Instance): |
paul@554 | 101 | |
paul@554 | 102 | "A constant object with no context." |
paul@554 | 103 | |
paul@554 | 104 | def __init__(self, value): |
paul@554 | 105 | Instance.__init__(self) |
paul@554 | 106 | self.value = value |
paul@554 | 107 | |
paul@554 | 108 | def get_value(self): |
paul@554 | 109 | return self.value |
paul@554 | 110 | |
paul@554 | 111 | def __repr__(self): |
paul@554 | 112 | if self.location is not None: |
paul@554 | 113 | return "Const(%r, location=%r)" % (self.value, self.location) |
paul@554 | 114 | else: |
paul@554 | 115 | return "Const(%r)" % self.value |
paul@554 | 116 | |
paul@554 | 117 | __shortrepr__ = __repr__ |
paul@554 | 118 | |
paul@554 | 119 | # Support constants as dictionary keys in order to build constant tables. |
paul@554 | 120 | |
paul@554 | 121 | def __eq__(self, other): |
paul@554 | 122 | return other is not None and isinstance(other, Const) and \ |
paul@554 | 123 | self.value == other.value and self.value.__class__ is other.value.__class__ |
paul@554 | 124 | |
paul@554 | 125 | def __ne__(self, other): |
paul@554 | 126 | return not self.__eq__(other) |
paul@554 | 127 | |
paul@554 | 128 | def __hash__(self): |
paul@554 | 129 | return hash(self.value) |
paul@554 | 130 | |
paul@554 | 131 | # Constants are instances of various built-in types. |
paul@554 | 132 | |
paul@554 | 133 | def value_type_name(self): |
paul@554 | 134 | return ".".join(self.value_type_name_parts()) |
paul@554 | 135 | |
paul@554 | 136 | def value_type_name_parts(self): |
paul@619 | 137 | return "__builtins__", self.get_class_name() |
paul@619 | 138 | |
paul@619 | 139 | def get_class_name(self): |
paul@619 | 140 | return self.value.__class__.__name__ |
paul@554 | 141 | |
paul@554 | 142 | # vim: tabstop=4 expandtab shiftwidth=4 |