1 #!/usr/bin/env python 2 3 """ 4 Result abstractions. 5 6 Copyright (C) 2016, 2017, 2023, 2024 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from referencing import Reference 23 24 # Classes representing inspection and translation observations. 25 26 class Result: 27 28 "An abstract expression result." 29 30 def is_name(self): 31 return False 32 33 def is_global_name(self): 34 return False 35 36 def reference(self): 37 return None 38 39 def references(self): 40 return None 41 42 def access_location(self): 43 return None 44 45 def access_locations(self): 46 return None 47 48 def context(self): 49 return None 50 51 def context_verified(self): 52 return None 53 54 def discards_temporary(self, test=True): 55 return None 56 57 def get_name(self): 58 return None 59 60 def get_origin(self): 61 return None 62 63 def static(self): 64 return None 65 66 def final(self): 67 return None 68 69 def has_kind(self, kinds): 70 return False 71 72 # Support for formulating expressions for direct testing. 73 74 def yields_integer(self): 75 return False 76 77 def apply_test(self): 78 79 "Return the result in a form suitable for direct testing." 80 81 if self.yields_integer(): 82 return "__INTEGER(%s)" % self 83 else: 84 return "__BOOL(%s)" % self 85 86 class AccessRef(Result): 87 88 """ 89 A reference to an attribute access that is generally only returned from a 90 processed access for possible initialiser resolution for assignments. 91 """ 92 93 def __init__(self, original_name, attrnames, number): 94 self.original_name = original_name 95 self.attrnames = attrnames 96 self.number = number 97 98 def __repr__(self): 99 return "AccessRef(%r, %r, %r)" % (self.original_name, self.attrnames, self.number) 100 101 class InvocationRef(Result): 102 103 "An invocation of a name reference." 104 105 def __init__(self, name_ref): 106 self.name_ref = name_ref 107 108 def reference(self): 109 origin = self.name_ref.get_origin() 110 if origin: 111 return Reference("<invoke>", origin) 112 else: 113 return Reference("<var>") 114 115 def __repr__(self): 116 return "InvocationRef(%r)" % self.name_ref 117 118 class NameRef(Result): 119 120 "A reference to a name." 121 122 def __init__(self, name, expr=None, is_global=False): 123 self.name = name 124 self.expr = expr 125 self.is_global = is_global 126 127 def is_name(self): 128 return True 129 130 def is_global_name(self): 131 return self.is_global 132 133 def final(self): 134 return None 135 136 def __repr__(self): 137 return "NameRef(%r, %r, %r)" % (self.name, self.expr, self.is_global) 138 139 class LocalNameRef(NameRef): 140 141 "A reference to a local name." 142 143 def __init__(self, name, number): 144 NameRef.__init__(self, name, is_global=False) 145 self.number = number 146 147 def __repr__(self): 148 return "LocalNameRef(%r, %r)" % (self.name, self.number) 149 150 class ResolvedRef: 151 152 "A resolved reference mix-in." 153 154 def __init__(self, ref): 155 self.ref = ref 156 157 def reference(self): 158 return self.ref 159 160 def references(self): 161 return [self.ref] 162 163 def get_name(self): 164 return self.ref and self.ref.get_name() or None 165 166 def get_origin(self): 167 return self.ref and self.ref.get_origin() or None 168 169 def static(self): 170 return self.ref and self.ref.static() or None 171 172 def final(self): 173 return self.ref and self.ref.final() or None 174 175 def has_kind(self, kinds): 176 return self.ref and self.ref.has_kind(kinds) 177 178 def is_constant_alias(self): 179 return self.ref and self.ref.is_constant_alias() 180 181 def is_well_defined_instance(self): 182 return self.ref and self.ref.is_well_defined_instance() 183 184 class ResolvedNameRef(ResolvedRef, NameRef): 185 186 "A resolved name-based reference." 187 188 def __init__(self, name, ref, expr=None, is_global=False): 189 NameRef.__init__(self, name, expr, is_global) 190 ResolvedRef.__init__(self, ref) 191 192 def __repr__(self): 193 return "ResolvedNameRef(%r, %r, %r, %r)" % (self.name, self.ref, self.expr, self.is_global) 194 195 class ConstantValueRef(ResolvedNameRef): 196 197 "A constant reference representing a single literal value." 198 199 def __init__(self, name, ref, value, number=None): 200 ResolvedNameRef.__init__(self, name, ref) 201 self.value = value 202 self.number = number 203 204 def __repr__(self): 205 return "ConstantValueRef(%r, %r, %r, %r)" % (self.name, self.ref, self.value, self.number) 206 207 class InstanceRef(ResolvedRef, Result): 208 209 "An instance reference." 210 211 def reference(self): 212 return self.ref 213 214 def __repr__(self): 215 return "InstanceRef(%r)" % self.ref 216 217 class LiteralSequenceRef(ResolvedNameRef): 218 219 "A reference representing a sequence of values." 220 221 def __init__(self, name, ref, node, items=None): 222 ResolvedNameRef.__init__(self, name, ref) 223 self.node = node 224 self.items = items 225 226 def __repr__(self): 227 return "LiteralSequenceRef(%r, %r, %r, %r)" % (self.name, self.ref, self.node, self.items) 228 229 class MultipleRef(Result): 230 231 "A multiple outcome result." 232 233 def __init__(self, results): 234 self.results = results 235 236 def reference(self): 237 refs = set(self.references()) 238 ref = len(refs) == 1 and list(refs)[0] or Reference("<var>") 239 240 def references(self): 241 refs = [] 242 for result in self.results: 243 refs.append(result.reference()) 244 return refs 245 246 def __repr__(self): 247 return "MultipleRef(%r)" % self.results 248 249 class VariableRef(Result): 250 251 "A variable reference." 252 253 def __repr__(self): 254 return "VariableRef()" 255 256 # vim: tabstop=4 expandtab shiftwidth=4