dom/bindings/parser/WebIDL.py

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 4
michael@0 5 """ A WebIDL parser. """
michael@0 6
michael@0 7 from ply import lex, yacc
michael@0 8 import re
michael@0 9 import os
michael@0 10 import traceback
michael@0 11 import math
michael@0 12
michael@0 13 # Machinery
michael@0 14
michael@0 15 def parseInt(literal):
michael@0 16 string = literal
michael@0 17 sign = 0
michael@0 18 base = 0
michael@0 19
michael@0 20 if string[0] == '-':
michael@0 21 sign = -1
michael@0 22 string = string[1:]
michael@0 23 else:
michael@0 24 sign = 1
michael@0 25
michael@0 26 if string[0] == '0' and len(string) > 1:
michael@0 27 if string[1] == 'x' or string[1] == 'X':
michael@0 28 base = 16
michael@0 29 string = string[2:]
michael@0 30 else:
michael@0 31 base = 8
michael@0 32 string = string[1:]
michael@0 33 else:
michael@0 34 base = 10
michael@0 35
michael@0 36 value = int(string, base)
michael@0 37 return value * sign
michael@0 38
michael@0 39 # Magic for creating enums
michael@0 40 def M_add_class_attribs(attribs, start):
michael@0 41 def foo(name, bases, dict_):
michael@0 42 for v, k in enumerate(attribs):
michael@0 43 dict_[k] = start + v
michael@0 44 assert 'length' not in dict_
michael@0 45 dict_['length'] = start + len(attribs)
michael@0 46 return type(name, bases, dict_)
michael@0 47 return foo
michael@0 48
michael@0 49 def enum(*names, **kw):
michael@0 50 if len(kw) == 1:
michael@0 51 base = kw['base'].__class__
michael@0 52 start = base.length
michael@0 53 else:
michael@0 54 assert len(kw) == 0
michael@0 55 base = object
michael@0 56 start = 0
michael@0 57 class Foo(base):
michael@0 58 __metaclass__ = M_add_class_attribs(names, start)
michael@0 59 def __setattr__(self, name, value): # this makes it read-only
michael@0 60 raise NotImplementedError
michael@0 61 return Foo()
michael@0 62
michael@0 63 class WebIDLError(Exception):
michael@0 64 def __init__(self, message, locations, warning=False):
michael@0 65 self.message = message
michael@0 66 self.locations = [str(loc) for loc in locations]
michael@0 67 self.warning = warning
michael@0 68
michael@0 69 def __str__(self):
michael@0 70 return "%s: %s%s%s" % (self.warning and 'warning' or 'error',
michael@0 71 self.message,
michael@0 72 ", " if len(self.locations) != 0 else "",
michael@0 73 "\n".join(self.locations))
michael@0 74
michael@0 75 class Location(object):
michael@0 76 def __init__(self, lexer, lineno, lexpos, filename):
michael@0 77 self._line = None
michael@0 78 self._lineno = lineno
michael@0 79 self._lexpos = lexpos
michael@0 80 self._lexdata = lexer.lexdata
michael@0 81 self._file = filename if filename else "<unknown>"
michael@0 82
michael@0 83 def __eq__(self, other):
michael@0 84 return self._lexpos == other._lexpos and \
michael@0 85 self._file == other._file
michael@0 86
michael@0 87 def filename(self):
michael@0 88 return self._file
michael@0 89
michael@0 90 def resolve(self):
michael@0 91 if self._line:
michael@0 92 return
michael@0 93
michael@0 94 startofline = self._lexdata.rfind('\n', 0, self._lexpos) + 1
michael@0 95 endofline = self._lexdata.find('\n', self._lexpos, self._lexpos + 80)
michael@0 96 if endofline != -1:
michael@0 97 self._line = self._lexdata[startofline:endofline]
michael@0 98 else:
michael@0 99 self._line = self._lexdata[startofline:]
michael@0 100 self._colno = self._lexpos - startofline
michael@0 101
michael@0 102 # Our line number seems to point to the start of self._lexdata
michael@0 103 self._lineno += self._lexdata.count('\n', 0, startofline)
michael@0 104
michael@0 105 def get(self):
michael@0 106 self.resolve()
michael@0 107 return "%s line %s:%s" % (self._file, self._lineno, self._colno)
michael@0 108
michael@0 109 def _pointerline(self):
michael@0 110 return " " * self._colno + "^"
michael@0 111
michael@0 112 def __str__(self):
michael@0 113 self.resolve()
michael@0 114 return "%s line %s:%s\n%s\n%s" % (self._file, self._lineno, self._colno,
michael@0 115 self._line, self._pointerline())
michael@0 116
michael@0 117 class BuiltinLocation(object):
michael@0 118 def __init__(self, text):
michael@0 119 self.msg = text + "\n"
michael@0 120
michael@0 121 def __eq__(self, other):
michael@0 122 return isinstance(other, BuiltinLocation) and \
michael@0 123 self.msg == other.msg
michael@0 124
michael@0 125 def filename(self):
michael@0 126 return '<builtin>'
michael@0 127
michael@0 128 def resolve(self):
michael@0 129 pass
michael@0 130
michael@0 131 def get(self):
michael@0 132 return self.msg
michael@0 133
michael@0 134 def __str__(self):
michael@0 135 return self.get()
michael@0 136
michael@0 137
michael@0 138 # Data Model
michael@0 139
michael@0 140 class IDLObject(object):
michael@0 141 def __init__(self, location):
michael@0 142 self.location = location
michael@0 143 self.userData = dict()
michael@0 144
michael@0 145 def filename(self):
michael@0 146 return self.location.filename()
michael@0 147
michael@0 148 def isInterface(self):
michael@0 149 return False
michael@0 150
michael@0 151 def isEnum(self):
michael@0 152 return False
michael@0 153
michael@0 154 def isCallback(self):
michael@0 155 return False
michael@0 156
michael@0 157 def isType(self):
michael@0 158 return False
michael@0 159
michael@0 160 def isDictionary(self):
michael@0 161 return False;
michael@0 162
michael@0 163 def isUnion(self):
michael@0 164 return False
michael@0 165
michael@0 166 def getUserData(self, key, default):
michael@0 167 return self.userData.get(key, default)
michael@0 168
michael@0 169 def setUserData(self, key, value):
michael@0 170 self.userData[key] = value
michael@0 171
michael@0 172 def addExtendedAttributes(self, attrs):
michael@0 173 assert False # Override me!
michael@0 174
michael@0 175 def handleExtendedAttribute(self, attr):
michael@0 176 assert False # Override me!
michael@0 177
michael@0 178 def _getDependentObjects(self):
michael@0 179 assert False # Override me!
michael@0 180
michael@0 181 def getDeps(self, visited=None):
michael@0 182 """ Return a set of files that this object depends on. If any of
michael@0 183 these files are changed the parser needs to be rerun to regenerate
michael@0 184 a new IDLObject.
michael@0 185
michael@0 186 The visited argument is a set of all the objects already visited.
michael@0 187 We must test to see if we are in it, and if so, do nothing. This
michael@0 188 prevents infinite recursion."""
michael@0 189
michael@0 190 # NB: We can't use visited=set() above because the default value is
michael@0 191 # evaluated when the def statement is evaluated, not when the function
michael@0 192 # is executed, so there would be one set for all invocations.
michael@0 193 if visited == None:
michael@0 194 visited = set()
michael@0 195
michael@0 196 if self in visited:
michael@0 197 return set()
michael@0 198
michael@0 199 visited.add(self)
michael@0 200
michael@0 201 deps = set()
michael@0 202 if self.filename() != "<builtin>":
michael@0 203 deps.add(self.filename())
michael@0 204
michael@0 205 for d in self._getDependentObjects():
michael@0 206 deps = deps.union(d.getDeps(visited))
michael@0 207
michael@0 208 return deps
michael@0 209
michael@0 210 class IDLScope(IDLObject):
michael@0 211 def __init__(self, location, parentScope, identifier):
michael@0 212 IDLObject.__init__(self, location)
michael@0 213
michael@0 214 self.parentScope = parentScope
michael@0 215 if identifier:
michael@0 216 assert isinstance(identifier, IDLIdentifier)
michael@0 217 self._name = identifier
michael@0 218 else:
michael@0 219 self._name = None
michael@0 220
michael@0 221 self._dict = {}
michael@0 222
michael@0 223 def __str__(self):
michael@0 224 return self.QName()
michael@0 225
michael@0 226 def QName(self):
michael@0 227 if self._name:
michael@0 228 return self._name.QName() + "::"
michael@0 229 return "::"
michael@0 230
michael@0 231 def ensureUnique(self, identifier, object):
michael@0 232 """
michael@0 233 Ensure that there is at most one 'identifier' in scope ('self').
michael@0 234 Note that object can be None. This occurs if we end up here for an
michael@0 235 interface type we haven't seen yet.
michael@0 236 """
michael@0 237 assert isinstance(identifier, IDLUnresolvedIdentifier)
michael@0 238 assert not object or isinstance(object, IDLObjectWithIdentifier)
michael@0 239 assert not object or object.identifier == identifier
michael@0 240
michael@0 241 if identifier.name in self._dict:
michael@0 242 if not object:
michael@0 243 return
michael@0 244
michael@0 245 # ensureUnique twice with the same object is not allowed
michael@0 246 assert id(object) != id(self._dict[identifier.name])
michael@0 247
michael@0 248 replacement = self.resolveIdentifierConflict(self, identifier,
michael@0 249 self._dict[identifier.name],
michael@0 250 object)
michael@0 251 self._dict[identifier.name] = replacement
michael@0 252 return
michael@0 253
michael@0 254 assert object
michael@0 255
michael@0 256 self._dict[identifier.name] = object
michael@0 257
michael@0 258 def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
michael@0 259 if isinstance(originalObject, IDLExternalInterface) and \
michael@0 260 isinstance(newObject, IDLExternalInterface) and \
michael@0 261 originalObject.identifier.name == newObject.identifier.name:
michael@0 262 return originalObject
michael@0 263
michael@0 264 if (isinstance(originalObject, IDLExternalInterface) or
michael@0 265 isinstance(newObject, IDLExternalInterface)):
michael@0 266 raise WebIDLError(
michael@0 267 "Name collision between "
michael@0 268 "interface declarations for identifier '%s' at '%s' and '%s'"
michael@0 269 % (identifier.name,
michael@0 270 originalObject.location, newObject.location), [])
michael@0 271
michael@0 272 # We do the merging of overloads here as opposed to in IDLInterface
michael@0 273 # because we need to merge overloads of NamedConstructors and we need to
michael@0 274 # detect conflicts in those across interfaces. See also the comment in
michael@0 275 # IDLInterface.addExtendedAttributes for "NamedConstructor".
michael@0 276 if originalObject.tag == IDLInterfaceMember.Tags.Method and \
michael@0 277 newObject.tag == IDLInterfaceMember.Tags.Method:
michael@0 278 return originalObject.addOverload(newObject)
michael@0 279
michael@0 280 # Default to throwing, derived classes can override.
michael@0 281 conflictdesc = "\n\t%s at %s\n\t%s at %s" % \
michael@0 282 (originalObject, originalObject.location, newObject, newObject.location)
michael@0 283
michael@0 284 raise WebIDLError(
michael@0 285 "Multiple unresolvable definitions of identifier '%s' in scope '%s%s"
michael@0 286 % (identifier.name, str(self), conflictdesc), [])
michael@0 287
michael@0 288 def _lookupIdentifier(self, identifier):
michael@0 289 return self._dict[identifier.name]
michael@0 290
michael@0 291 def lookupIdentifier(self, identifier):
michael@0 292 assert isinstance(identifier, IDLIdentifier)
michael@0 293 assert identifier.scope == self
michael@0 294 return self._lookupIdentifier(identifier)
michael@0 295
michael@0 296 class IDLIdentifier(IDLObject):
michael@0 297 def __init__(self, location, scope, name):
michael@0 298 IDLObject.__init__(self, location)
michael@0 299
michael@0 300 self.name = name
michael@0 301 assert isinstance(scope, IDLScope)
michael@0 302 self.scope = scope
michael@0 303
michael@0 304 def __str__(self):
michael@0 305 return self.QName()
michael@0 306
michael@0 307 def QName(self):
michael@0 308 return self.scope.QName() + self.name
michael@0 309
michael@0 310 def __hash__(self):
michael@0 311 return self.QName().__hash__()
michael@0 312
michael@0 313 def __eq__(self, other):
michael@0 314 return self.QName() == other.QName()
michael@0 315
michael@0 316 def object(self):
michael@0 317 return self.scope.lookupIdentifier(self)
michael@0 318
michael@0 319 class IDLUnresolvedIdentifier(IDLObject):
michael@0 320 def __init__(self, location, name, allowDoubleUnderscore = False,
michael@0 321 allowForbidden = False):
michael@0 322 IDLObject.__init__(self, location)
michael@0 323
michael@0 324 assert len(name) > 0
michael@0 325
michael@0 326 if name[:2] == "__" and name != "__content" and name != "___noSuchMethod__" and not allowDoubleUnderscore:
michael@0 327 raise WebIDLError("Identifiers beginning with __ are reserved",
michael@0 328 [location])
michael@0 329 if name[0] == '_' and not allowDoubleUnderscore:
michael@0 330 name = name[1:]
michael@0 331 # TODO: Bug 872377, Restore "toJSON" to below list.
michael@0 332 # We sometimes need custom serialization, so allow toJSON for now.
michael@0 333 if (name in ["constructor", "toString"] and
michael@0 334 not allowForbidden):
michael@0 335 raise WebIDLError("Cannot use reserved identifier '%s'" % (name),
michael@0 336 [location])
michael@0 337
michael@0 338 self.name = name
michael@0 339
michael@0 340 def __str__(self):
michael@0 341 return self.QName()
michael@0 342
michael@0 343 def QName(self):
michael@0 344 return "<unresolved scope>::" + self.name
michael@0 345
michael@0 346 def resolve(self, scope, object):
michael@0 347 assert isinstance(scope, IDLScope)
michael@0 348 assert not object or isinstance(object, IDLObjectWithIdentifier)
michael@0 349 assert not object or object.identifier == self
michael@0 350
michael@0 351 scope.ensureUnique(self, object)
michael@0 352
michael@0 353 identifier = IDLIdentifier(self.location, scope, self.name)
michael@0 354 if object:
michael@0 355 object.identifier = identifier
michael@0 356 return identifier
michael@0 357
michael@0 358 def finish(self):
michael@0 359 assert False # Should replace with a resolved identifier first.
michael@0 360
michael@0 361 class IDLObjectWithIdentifier(IDLObject):
michael@0 362 def __init__(self, location, parentScope, identifier):
michael@0 363 IDLObject.__init__(self, location)
michael@0 364
michael@0 365 assert isinstance(identifier, IDLUnresolvedIdentifier)
michael@0 366
michael@0 367 self.identifier = identifier
michael@0 368
michael@0 369 if parentScope:
michael@0 370 self.resolve(parentScope)
michael@0 371
michael@0 372 self.treatNullAs = "Default"
michael@0 373
michael@0 374 def resolve(self, parentScope):
michael@0 375 assert isinstance(parentScope, IDLScope)
michael@0 376 assert isinstance(self.identifier, IDLUnresolvedIdentifier)
michael@0 377 self.identifier.resolve(parentScope, self)
michael@0 378
michael@0 379 def checkForStringHandlingExtendedAttributes(self, attrs,
michael@0 380 isDictionaryMember=False,
michael@0 381 isOptional=False):
michael@0 382 """
michael@0 383 A helper function to deal with TreatNullAs. Returns the list
michael@0 384 of attrs it didn't handle itself.
michael@0 385 """
michael@0 386 assert isinstance(self, IDLArgument) or isinstance(self, IDLAttribute)
michael@0 387 unhandledAttrs = list()
michael@0 388 for attr in attrs:
michael@0 389 if not attr.hasValue():
michael@0 390 unhandledAttrs.append(attr)
michael@0 391 continue
michael@0 392
michael@0 393 identifier = attr.identifier()
michael@0 394 value = attr.value()
michael@0 395 if identifier == "TreatNullAs":
michael@0 396 if not self.type.isDOMString() or self.type.nullable():
michael@0 397 raise WebIDLError("[TreatNullAs] is only allowed on "
michael@0 398 "arguments or attributes whose type is "
michael@0 399 "DOMString",
michael@0 400 [self.location])
michael@0 401 if isDictionaryMember:
michael@0 402 raise WebIDLError("[TreatNullAs] is not allowed for "
michael@0 403 "dictionary members", [self.location])
michael@0 404 if value != 'EmptyString':
michael@0 405 raise WebIDLError("[TreatNullAs] must take the identifier "
michael@0 406 "'EmptyString', not '%s'" % value,
michael@0 407 [self.location])
michael@0 408 self.treatNullAs = value
michael@0 409 else:
michael@0 410 unhandledAttrs.append(attr)
michael@0 411
michael@0 412 return unhandledAttrs
michael@0 413
michael@0 414 class IDLObjectWithScope(IDLObjectWithIdentifier, IDLScope):
michael@0 415 def __init__(self, location, parentScope, identifier):
michael@0 416 assert isinstance(identifier, IDLUnresolvedIdentifier)
michael@0 417
michael@0 418 IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier)
michael@0 419 IDLScope.__init__(self, location, parentScope, self.identifier)
michael@0 420
michael@0 421 class IDLIdentifierPlaceholder(IDLObjectWithIdentifier):
michael@0 422 def __init__(self, location, identifier):
michael@0 423 assert isinstance(identifier, IDLUnresolvedIdentifier)
michael@0 424 IDLObjectWithIdentifier.__init__(self, location, None, identifier)
michael@0 425
michael@0 426 def finish(self, scope):
michael@0 427 try:
michael@0 428 scope._lookupIdentifier(self.identifier)
michael@0 429 except:
michael@0 430 raise WebIDLError("Unresolved type '%s'." % self.identifier,
michael@0 431 [self.location])
michael@0 432
michael@0 433 obj = self.identifier.resolve(scope, None)
michael@0 434 return scope.lookupIdentifier(obj)
michael@0 435
michael@0 436 class IDLExternalInterface(IDLObjectWithIdentifier):
michael@0 437 def __init__(self, location, parentScope, identifier):
michael@0 438 assert isinstance(identifier, IDLUnresolvedIdentifier)
michael@0 439 assert isinstance(parentScope, IDLScope)
michael@0 440 self.parent = None
michael@0 441 IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier)
michael@0 442 IDLObjectWithIdentifier.resolve(self, parentScope)
michael@0 443
michael@0 444 def finish(self, scope):
michael@0 445 pass
michael@0 446
michael@0 447 def validate(self):
michael@0 448 pass
michael@0 449
michael@0 450 def isExternal(self):
michael@0 451 return True
michael@0 452
michael@0 453 def isInterface(self):
michael@0 454 return True
michael@0 455
michael@0 456 def isConsequential(self):
michael@0 457 return False
michael@0 458
michael@0 459 def addExtendedAttributes(self, attrs):
michael@0 460 assert len(attrs) == 0
michael@0 461
michael@0 462 def resolve(self, parentScope):
michael@0 463 pass
michael@0 464
michael@0 465 def getJSImplementation(self):
michael@0 466 return None
michael@0 467
michael@0 468 def isJSImplemented(self):
michael@0 469 return False
michael@0 470
michael@0 471 def getNavigatorProperty(self):
michael@0 472 return None
michael@0 473
michael@0 474 def _getDependentObjects(self):
michael@0 475 return set()
michael@0 476
michael@0 477 class IDLInterface(IDLObjectWithScope):
michael@0 478 def __init__(self, location, parentScope, name, parent, members,
michael@0 479 isPartial):
michael@0 480 assert isinstance(parentScope, IDLScope)
michael@0 481 assert isinstance(name, IDLUnresolvedIdentifier)
michael@0 482 assert not isPartial or not parent
michael@0 483
michael@0 484 self.parent = None
michael@0 485 self._callback = False
michael@0 486 self._finished = False
michael@0 487 self.members = []
michael@0 488 # namedConstructors needs deterministic ordering because bindings code
michael@0 489 # outputs the constructs in the order that namedConstructors enumerates
michael@0 490 # them.
michael@0 491 self.namedConstructors = list()
michael@0 492 self.implementedInterfaces = set()
michael@0 493 self._consequential = False
michael@0 494 self._isPartial = True
michael@0 495 # self.interfacesBasedOnSelf is the set of interfaces that inherit from
michael@0 496 # self or have self as a consequential interface, including self itself.
michael@0 497 # Used for distinguishability checking.
michael@0 498 self.interfacesBasedOnSelf = set([self])
michael@0 499 # self.interfacesImplementingSelf is the set of interfaces that directly
michael@0 500 # have self as a consequential interface
michael@0 501 self.interfacesImplementingSelf = set()
michael@0 502 self._hasChildInterfaces = False
michael@0 503 self._isOnGlobalProtoChain = False
michael@0 504 # Tracking of the number of reserved slots we need for our
michael@0 505 # members and those of ancestor interfaces.
michael@0 506 self.totalMembersInSlots = 0
michael@0 507 # Tracking of the number of own own members we have in slots
michael@0 508 self._ownMembersInSlots = 0
michael@0 509
michael@0 510 IDLObjectWithScope.__init__(self, location, parentScope, name)
michael@0 511
michael@0 512 if not isPartial:
michael@0 513 self.setNonPartial(location, parent, members)
michael@0 514 else:
michael@0 515 # Just remember our members for now
michael@0 516 self.members = members
michael@0 517
michael@0 518 def __str__(self):
michael@0 519 return "Interface '%s'" % self.identifier.name
michael@0 520
michael@0 521 def ctor(self):
michael@0 522 identifier = IDLUnresolvedIdentifier(self.location, "constructor",
michael@0 523 allowForbidden=True)
michael@0 524 try:
michael@0 525 return self._lookupIdentifier(identifier)
michael@0 526 except:
michael@0 527 return None
michael@0 528
michael@0 529 def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
michael@0 530 assert isinstance(scope, IDLScope)
michael@0 531 assert isinstance(originalObject, IDLInterfaceMember)
michael@0 532 assert isinstance(newObject, IDLInterfaceMember)
michael@0 533
michael@0 534 retval = IDLScope.resolveIdentifierConflict(self, scope, identifier,
michael@0 535 originalObject, newObject)
michael@0 536
michael@0 537 # Might be a ctor, which isn't in self.members
michael@0 538 if newObject in self.members:
michael@0 539 self.members.remove(newObject)
michael@0 540 return retval
michael@0 541
michael@0 542 def finish(self, scope):
michael@0 543 if self._finished:
michael@0 544 return
michael@0 545
michael@0 546 self._finished = True
michael@0 547
michael@0 548 if self._isPartial:
michael@0 549 raise WebIDLError("Interface %s does not have a non-partial "
michael@0 550 "declaration" % self.identifier.name,
michael@0 551 [self.location])
michael@0 552
michael@0 553 assert not self.parent or isinstance(self.parent, IDLIdentifierPlaceholder)
michael@0 554 parent = self.parent.finish(scope) if self.parent else None
michael@0 555 if parent and isinstance(parent, IDLExternalInterface):
michael@0 556 raise WebIDLError("%s inherits from %s which does not have "
michael@0 557 "a definition" %
michael@0 558 (self.identifier.name,
michael@0 559 self.parent.identifier.name),
michael@0 560 [self.location])
michael@0 561 assert not parent or isinstance(parent, IDLInterface)
michael@0 562
michael@0 563 self.parent = parent
michael@0 564
michael@0 565 assert iter(self.members)
michael@0 566
michael@0 567 if self.parent:
michael@0 568 self.parent.finish(scope)
michael@0 569
michael@0 570 self.parent._hasChildInterfaces = True
michael@0 571
michael@0 572 self.totalMembersInSlots = self.parent.totalMembersInSlots
michael@0 573
michael@0 574 # Interfaces with [Global] must not have anything inherit from them
michael@0 575 if self.parent.getExtendedAttribute("Global"):
michael@0 576 # Note: This is not a self.parent.isOnGlobalProtoChain() check
michael@0 577 # because ancestors of a [Global] interface can have other
michael@0 578 # descendants.
michael@0 579 raise WebIDLError("[Global] interface has another interface "
michael@0 580 "inheriting from it",
michael@0 581 [self.location, self.parent.location])
michael@0 582
michael@0 583 # Callbacks must not inherit from non-callbacks or inherit from
michael@0 584 # anything that has consequential interfaces.
michael@0 585 # XXXbz Can non-callbacks inherit from callbacks? Spec issue pending.
michael@0 586 # XXXbz Can callbacks have consequential interfaces? Spec issue pending
michael@0 587 if self.isCallback():
michael@0 588 if not self.parent.isCallback():
michael@0 589 raise WebIDLError("Callback interface %s inheriting from "
michael@0 590 "non-callback interface %s" %
michael@0 591 (self.identifier.name,
michael@0 592 self.parent.identifier.name),
michael@0 593 [self.location, self.parent.location])
michael@0 594 elif self.parent.isCallback():
michael@0 595 raise WebIDLError("Non-callback interface %s inheriting from "
michael@0 596 "callback interface %s" %
michael@0 597 (self.identifier.name,
michael@0 598 self.parent.identifier.name),
michael@0 599 [self.location, self.parent.location])
michael@0 600
michael@0 601 for iface in self.implementedInterfaces:
michael@0 602 iface.finish(scope)
michael@0 603
michael@0 604 cycleInGraph = self.findInterfaceLoopPoint(self)
michael@0 605 if cycleInGraph:
michael@0 606 raise WebIDLError("Interface %s has itself as ancestor or "
michael@0 607 "implemented interface" % self.identifier.name,
michael@0 608 [self.location, cycleInGraph.location])
michael@0 609
michael@0 610 if self.isCallback():
michael@0 611 # "implements" should have made sure we have no
michael@0 612 # consequential interfaces.
michael@0 613 assert len(self.getConsequentialInterfaces()) == 0
michael@0 614 # And that we're not consequential.
michael@0 615 assert not self.isConsequential()
michael@0 616
michael@0 617 # Now resolve() and finish() our members before importing the
michael@0 618 # ones from our implemented interfaces.
michael@0 619
michael@0 620 # resolve() will modify self.members, so we need to iterate
michael@0 621 # over a copy of the member list here.
michael@0 622 for member in list(self.members):
michael@0 623 member.resolve(self)
michael@0 624
michael@0 625 for member in self.members:
michael@0 626 member.finish(scope)
michael@0 627
michael@0 628 ctor = self.ctor()
michael@0 629 if ctor is not None:
michael@0 630 ctor.finish(scope)
michael@0 631
michael@0 632 for ctor in self.namedConstructors:
michael@0 633 ctor.finish(scope)
michael@0 634
michael@0 635 # Make a copy of our member list, so things that implement us
michael@0 636 # can get those without all the stuff we implement ourselves
michael@0 637 # admixed.
michael@0 638 self.originalMembers = list(self.members)
michael@0 639
michael@0 640 # Import everything from our consequential interfaces into
michael@0 641 # self.members. Sort our consequential interfaces by name
michael@0 642 # just so we have a consistent order.
michael@0 643 for iface in sorted(self.getConsequentialInterfaces(),
michael@0 644 cmp=cmp,
michael@0 645 key=lambda x: x.identifier.name):
michael@0 646 # Flag the interface as being someone's consequential interface
michael@0 647 iface.setIsConsequentialInterfaceOf(self)
michael@0 648 additionalMembers = iface.originalMembers;
michael@0 649 for additionalMember in additionalMembers:
michael@0 650 for member in self.members:
michael@0 651 if additionalMember.identifier.name == member.identifier.name:
michael@0 652 raise WebIDLError(
michael@0 653 "Multiple definitions of %s on %s coming from 'implements' statements" %
michael@0 654 (member.identifier.name, self),
michael@0 655 [additionalMember.location, member.location])
michael@0 656 self.members.extend(additionalMembers)
michael@0 657 iface.interfacesImplementingSelf.add(self)
michael@0 658
michael@0 659 for ancestor in self.getInheritedInterfaces():
michael@0 660 ancestor.interfacesBasedOnSelf.add(self)
michael@0 661 for ancestorConsequential in ancestor.getConsequentialInterfaces():
michael@0 662 ancestorConsequential.interfacesBasedOnSelf.add(self)
michael@0 663
michael@0 664 for member in self.members:
michael@0 665 if (member.isAttr() and member.isUnforgeable() and
michael@0 666 not hasattr(member, "originatingInterface")):
michael@0 667 member.originatingInterface = self
michael@0 668
michael@0 669 # Compute slot indices for our members before we pull in
michael@0 670 # unforgeable members from our parent.
michael@0 671 for member in self.members:
michael@0 672 if (member.isAttr() and
michael@0 673 (member.getExtendedAttribute("StoreInSlot") or
michael@0 674 member.getExtendedAttribute("Cached"))):
michael@0 675 member.slotIndex = self.totalMembersInSlots
michael@0 676 self.totalMembersInSlots += 1
michael@0 677 if member.getExtendedAttribute("StoreInSlot"):
michael@0 678 self._ownMembersInSlots += 1
michael@0 679
michael@0 680 if self.parent:
michael@0 681 # Make sure we don't shadow any of the [Unforgeable] attributes on
michael@0 682 # our ancestor interfaces. We don't have to worry about
michael@0 683 # consequential interfaces here, because those have already been
michael@0 684 # imported into the relevant .members lists. And we don't have to
michael@0 685 # worry about anything other than our parent, because it has already
michael@0 686 # imported its ancestors unforgeable attributes into its member
michael@0 687 # list.
michael@0 688 for unforgeableAttr in (attr for attr in self.parent.members if
michael@0 689 attr.isAttr() and not attr.isStatic() and
michael@0 690 attr.isUnforgeable()):
michael@0 691 shadows = [ m for m in self.members if
michael@0 692 (m.isAttr() or m.isMethod()) and
michael@0 693 not m.isStatic() and
michael@0 694 m.identifier.name == unforgeableAttr.identifier.name ]
michael@0 695 if len(shadows) != 0:
michael@0 696 locs = [unforgeableAttr.location] + [ s.location for s
michael@0 697 in shadows ]
michael@0 698 raise WebIDLError("Interface %s shadows [Unforgeable] "
michael@0 699 "members of %s" %
michael@0 700 (self.identifier.name,
michael@0 701 ancestor.identifier.name),
michael@0 702 locs)
michael@0 703 # And now just stick it in our members, since we won't be
michael@0 704 # inheriting this down the proto chain. If we really cared we
michael@0 705 # could try to do something where we set up the unforgeable
michael@0 706 # attributes of ancestor interfaces, with their corresponding
michael@0 707 # getters, on our interface, but that gets pretty complicated
michael@0 708 # and seems unnecessary.
michael@0 709 self.members.append(unforgeableAttr)
michael@0 710
michael@0 711 # Ensure that there's at most one of each {named,indexed}
michael@0 712 # {getter,setter,creator,deleter}, at most one stringifier,
michael@0 713 # and at most one legacycaller. Note that this last is not
michael@0 714 # quite per spec, but in practice no one overloads
michael@0 715 # legacycallers.
michael@0 716 specialMembersSeen = {}
michael@0 717 for member in self.members:
michael@0 718 if not member.isMethod():
michael@0 719 continue
michael@0 720
michael@0 721 if member.isGetter():
michael@0 722 memberType = "getters"
michael@0 723 elif member.isSetter():
michael@0 724 memberType = "setters"
michael@0 725 elif member.isCreator():
michael@0 726 memberType = "creators"
michael@0 727 elif member.isDeleter():
michael@0 728 memberType = "deleters"
michael@0 729 elif member.isStringifier():
michael@0 730 memberType = "stringifiers"
michael@0 731 elif member.isJsonifier():
michael@0 732 memberType = "jsonifiers"
michael@0 733 elif member.isLegacycaller():
michael@0 734 memberType = "legacycallers"
michael@0 735 else:
michael@0 736 continue
michael@0 737
michael@0 738 if (memberType != "stringifiers" and memberType != "legacycallers" and
michael@0 739 memberType != "jsonifiers"):
michael@0 740 if member.isNamed():
michael@0 741 memberType = "named " + memberType
michael@0 742 else:
michael@0 743 assert member.isIndexed()
michael@0 744 memberType = "indexed " + memberType
michael@0 745
michael@0 746 if memberType in specialMembersSeen:
michael@0 747 raise WebIDLError("Multiple " + memberType + " on %s" % (self),
michael@0 748 [self.location,
michael@0 749 specialMembersSeen[memberType].location,
michael@0 750 member.location])
michael@0 751
michael@0 752 specialMembersSeen[memberType] = member
michael@0 753
michael@0 754 if self._isOnGlobalProtoChain:
michael@0 755 # Make sure we have no named setters, creators, or deleters
michael@0 756 for memberType in ["setter", "creator", "deleter"]:
michael@0 757 memberId = "named " + memberType + "s"
michael@0 758 if memberId in specialMembersSeen:
michael@0 759 raise WebIDLError("Interface with [Global] has a named %s" %
michael@0 760 memberType,
michael@0 761 [self.location,
michael@0 762 specialMembersSeen[memberId].location])
michael@0 763 # Make sure we're not [OverrideBuiltins]
michael@0 764 if self.getExtendedAttribute("OverrideBuiltins"):
michael@0 765 raise WebIDLError("Interface with [Global] also has "
michael@0 766 "[OverrideBuiltins]",
michael@0 767 [self.location])
michael@0 768 # Mark all of our ancestors as being on the global's proto chain too
michael@0 769 parent = self.parent
michael@0 770 while parent:
michael@0 771 # Must not inherit from an interface with [OverrideBuiltins]
michael@0 772 if parent.getExtendedAttribute("OverrideBuiltins"):
michael@0 773 raise WebIDLError("Interface with [Global] inherits from "
michael@0 774 "interface with [OverrideBuiltins]",
michael@0 775 [self.location, parent.location])
michael@0 776 parent._isOnGlobalProtoChain = True
michael@0 777 parent = parent.parent
michael@0 778
michael@0 779 def validate(self):
michael@0 780 for member in self.members:
michael@0 781 member.validate()
michael@0 782
michael@0 783 # Check that PutForwards refers to another attribute and that no
michael@0 784 # cycles exist in forwarded assignments.
michael@0 785 if member.isAttr():
michael@0 786 iface = self
michael@0 787 attr = member
michael@0 788 putForwards = attr.getExtendedAttribute("PutForwards")
michael@0 789 if putForwards and self.isCallback():
michael@0 790 raise WebIDLError("[PutForwards] used on an attribute "
michael@0 791 "on interface %s which is a callback "
michael@0 792 "interface" % self.identifier.name,
michael@0 793 [self.location, member.location])
michael@0 794
michael@0 795 while putForwards is not None:
michael@0 796 forwardIface = attr.type.unroll().inner
michael@0 797 fowardAttr = None
michael@0 798
michael@0 799 for forwardedMember in forwardIface.members:
michael@0 800 if (not forwardedMember.isAttr() or
michael@0 801 forwardedMember.identifier.name != putForwards[0]):
michael@0 802 continue
michael@0 803 if forwardedMember == member:
michael@0 804 raise WebIDLError("Cycle detected in forwarded "
michael@0 805 "assignments for attribute %s on "
michael@0 806 "%s" %
michael@0 807 (member.identifier.name, self),
michael@0 808 [member.location])
michael@0 809 fowardAttr = forwardedMember
michael@0 810 break
michael@0 811
michael@0 812 if fowardAttr is None:
michael@0 813 raise WebIDLError("Attribute %s on %s forwards to "
michael@0 814 "missing attribute %s" %
michael@0 815 (attr.identifier.name, iface, putForwards),
michael@0 816 [attr.location])
michael@0 817
michael@0 818 iface = forwardIface
michael@0 819 attr = fowardAttr
michael@0 820 putForwards = attr.getExtendedAttribute("PutForwards")
michael@0 821
michael@0 822
michael@0 823 def isInterface(self):
michael@0 824 return True
michael@0 825
michael@0 826 def isExternal(self):
michael@0 827 return False
michael@0 828
michael@0 829 def setIsConsequentialInterfaceOf(self, other):
michael@0 830 self._consequential = True
michael@0 831 self.interfacesBasedOnSelf.add(other)
michael@0 832
michael@0 833 def isConsequential(self):
michael@0 834 return self._consequential
michael@0 835
michael@0 836 def setCallback(self, value):
michael@0 837 self._callback = value
michael@0 838
michael@0 839 def isCallback(self):
michael@0 840 return self._callback
michael@0 841
michael@0 842 def isSingleOperationInterface(self):
michael@0 843 assert self.isCallback() or self.isJSImplemented()
michael@0 844 return (
michael@0 845 # JS-implemented things should never need the
michael@0 846 # this-handling weirdness of single-operation interfaces.
michael@0 847 not self.isJSImplemented() and
michael@0 848 # Not inheriting from another interface
michael@0 849 not self.parent and
michael@0 850 # No consequential interfaces
michael@0 851 len(self.getConsequentialInterfaces()) == 0 and
michael@0 852 # No attributes of any kinds
michael@0 853 not any(m.isAttr() for m in self.members) and
michael@0 854 # There is at least one regular operation, and all regular
michael@0 855 # operations have the same identifier
michael@0 856 len(set(m.identifier.name for m in self.members if
michael@0 857 m.isMethod() and not m.isStatic())) == 1)
michael@0 858
michael@0 859 def inheritanceDepth(self):
michael@0 860 depth = 0
michael@0 861 parent = self.parent
michael@0 862 while parent:
michael@0 863 depth = depth + 1
michael@0 864 parent = parent.parent
michael@0 865 return depth
michael@0 866
michael@0 867 def hasConstants(self):
michael@0 868 return any(m.isConst() for m in self.members)
michael@0 869
michael@0 870 def hasInterfaceObject(self):
michael@0 871 if self.isCallback():
michael@0 872 return self.hasConstants()
michael@0 873 return not hasattr(self, "_noInterfaceObject")
michael@0 874
michael@0 875 def hasInterfacePrototypeObject(self):
michael@0 876 return not self.isCallback() and self.getUserData('hasConcreteDescendant', False)
michael@0 877
michael@0 878 def addExtendedAttributes(self, attrs):
michael@0 879 self._extendedAttrDict = {}
michael@0 880 for attr in attrs:
michael@0 881 identifier = attr.identifier()
michael@0 882
michael@0 883 # Special cased attrs
michael@0 884 if identifier == "TreatNonCallableAsNull":
michael@0 885 raise WebIDLError("TreatNonCallableAsNull cannot be specified on interfaces",
michael@0 886 [attr.location, self.location])
michael@0 887 if identifier == "TreatNonObjectAsNull":
michael@0 888 raise WebIDLError("TreatNonObjectAsNull cannot be specified on interfaces",
michael@0 889 [attr.location, self.location])
michael@0 890 elif identifier == "NoInterfaceObject":
michael@0 891 if not attr.noArguments():
michael@0 892 raise WebIDLError("[NoInterfaceObject] must take no arguments",
michael@0 893 [attr.location])
michael@0 894
michael@0 895 if self.ctor():
michael@0 896 raise WebIDLError("Constructor and NoInterfaceObject are incompatible",
michael@0 897 [self.location])
michael@0 898
michael@0 899 self._noInterfaceObject = True
michael@0 900 elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor":
michael@0 901 if identifier == "Constructor" and not self.hasInterfaceObject():
michael@0 902 raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
michael@0 903 [self.location])
michael@0 904
michael@0 905 if identifier == "NamedConstructor" and not attr.hasValue():
michael@0 906 raise WebIDLError("NamedConstructor must either take an identifier or take a named argument list",
michael@0 907 [attr.location])
michael@0 908
michael@0 909 if identifier == "ChromeConstructor" and not self.hasInterfaceObject():
michael@0 910 raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
michael@0 911 [self.location])
michael@0 912
michael@0 913 args = attr.args() if attr.hasArgs() else []
michael@0 914
michael@0 915 retType = IDLWrapperType(self.location, self)
michael@0 916
michael@0 917 if identifier == "Constructor" or identifier == "ChromeConstructor":
michael@0 918 name = "constructor"
michael@0 919 allowForbidden = True
michael@0 920 else:
michael@0 921 name = attr.value()
michael@0 922 allowForbidden = False
michael@0 923
michael@0 924 methodIdentifier = IDLUnresolvedIdentifier(self.location, name,
michael@0 925 allowForbidden=allowForbidden)
michael@0 926
michael@0 927 method = IDLMethod(self.location, methodIdentifier, retType,
michael@0 928 args, static=True)
michael@0 929 # Constructors are always NewObject and are always
michael@0 930 # assumed to be able to throw (since there's no way to
michael@0 931 # indicate otherwise) and never have any other
michael@0 932 # extended attributes.
michael@0 933 method.addExtendedAttributes(
michael@0 934 [IDLExtendedAttribute(self.location, ("NewObject",)),
michael@0 935 IDLExtendedAttribute(self.location, ("Throws",))])
michael@0 936 if identifier == "ChromeConstructor":
michael@0 937 method.addExtendedAttributes(
michael@0 938 [IDLExtendedAttribute(self.location, ("ChromeOnly",))])
michael@0 939
michael@0 940 if identifier == "Constructor" or identifier == "ChromeConstructor":
michael@0 941 method.resolve(self)
michael@0 942 else:
michael@0 943 # We need to detect conflicts for NamedConstructors across
michael@0 944 # interfaces. We first call resolve on the parentScope,
michael@0 945 # which will merge all NamedConstructors with the same
michael@0 946 # identifier accross interfaces as overloads.
michael@0 947 method.resolve(self.parentScope)
michael@0 948
michael@0 949 # Then we look up the identifier on the parentScope. If the
michael@0 950 # result is the same as the method we're adding then it
michael@0 951 # hasn't been added as an overload and it's the first time
michael@0 952 # we've encountered a NamedConstructor with that identifier.
michael@0 953 # If the result is not the same as the method we're adding
michael@0 954 # then it has been added as an overload and we need to check
michael@0 955 # whether the result is actually one of our existing
michael@0 956 # NamedConstructors.
michael@0 957 newMethod = self.parentScope.lookupIdentifier(method.identifier)
michael@0 958 if newMethod == method:
michael@0 959 self.namedConstructors.append(method)
michael@0 960 elif not newMethod in self.namedConstructors:
michael@0 961 raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface",
michael@0 962 [method.location, newMethod.location])
michael@0 963 elif (identifier == "ArrayClass"):
michael@0 964 if not attr.noArguments():
michael@0 965 raise WebIDLError("[ArrayClass] must take no arguments",
michael@0 966 [attr.location])
michael@0 967 if self.parent:
michael@0 968 raise WebIDLError("[ArrayClass] must not be specified on "
michael@0 969 "an interface with inherited interfaces",
michael@0 970 [attr.location, self.location])
michael@0 971 elif identifier == "Global":
michael@0 972 if not attr.noArguments():
michael@0 973 raise WebIDLError("[Global] must take no arguments",
michael@0 974 [attr.location])
michael@0 975 self._isOnGlobalProtoChain = True
michael@0 976 elif (identifier == "NeedNewResolve" or
michael@0 977 identifier == "OverrideBuiltins" or
michael@0 978 identifier == "ChromeOnly"):
michael@0 979 # Known extended attributes that do not take values
michael@0 980 if not attr.noArguments():
michael@0 981 raise WebIDLError("[%s] must take no arguments" % identifier,
michael@0 982 [attr.location])
michael@0 983 elif (identifier == "Pref" or
michael@0 984 identifier == "JSImplementation" or
michael@0 985 identifier == "HeaderFile" or
michael@0 986 identifier == "NavigatorProperty" or
michael@0 987 identifier == "AvailableIn" or
michael@0 988 identifier == "Func"):
michael@0 989 # Known extended attributes that take a string value
michael@0 990 if not attr.hasValue():
michael@0 991 raise WebIDLError("[%s] must have a value" % identifier,
michael@0 992 [attr.location])
michael@0 993 else:
michael@0 994 raise WebIDLError("Unknown extended attribute %s on interface" % identifier,
michael@0 995 [attr.location])
michael@0 996
michael@0 997 attrlist = attr.listValue()
michael@0 998 self._extendedAttrDict[identifier] = attrlist if len(attrlist) else True
michael@0 999
michael@0 1000 def addImplementedInterface(self, implementedInterface):
michael@0 1001 assert(isinstance(implementedInterface, IDLInterface))
michael@0 1002 self.implementedInterfaces.add(implementedInterface)
michael@0 1003
michael@0 1004 def getInheritedInterfaces(self):
michael@0 1005 """
michael@0 1006 Returns a list of the interfaces this interface inherits from
michael@0 1007 (not including this interface itself). The list is in order
michael@0 1008 from most derived to least derived.
michael@0 1009 """
michael@0 1010 assert(self._finished)
michael@0 1011 if not self.parent:
michael@0 1012 return []
michael@0 1013 parentInterfaces = self.parent.getInheritedInterfaces()
michael@0 1014 parentInterfaces.insert(0, self.parent)
michael@0 1015 return parentInterfaces
michael@0 1016
michael@0 1017 def getConsequentialInterfaces(self):
michael@0 1018 assert(self._finished)
michael@0 1019 # The interfaces we implement directly
michael@0 1020 consequentialInterfaces = set(self.implementedInterfaces)
michael@0 1021
michael@0 1022 # And their inherited interfaces
michael@0 1023 for iface in self.implementedInterfaces:
michael@0 1024 consequentialInterfaces |= set(iface.getInheritedInterfaces())
michael@0 1025
michael@0 1026 # And now collect up the consequential interfaces of all of those
michael@0 1027 temp = set()
michael@0 1028 for iface in consequentialInterfaces:
michael@0 1029 temp |= iface.getConsequentialInterfaces()
michael@0 1030
michael@0 1031 return consequentialInterfaces | temp
michael@0 1032
michael@0 1033 def findInterfaceLoopPoint(self, otherInterface):
michael@0 1034 """
michael@0 1035 Finds an interface, amongst our ancestors and consequential interfaces,
michael@0 1036 that inherits from otherInterface or implements otherInterface
michael@0 1037 directly. If there is no such interface, returns None.
michael@0 1038 """
michael@0 1039 if self.parent:
michael@0 1040 if self.parent == otherInterface:
michael@0 1041 return self
michael@0 1042 loopPoint = self.parent.findInterfaceLoopPoint(otherInterface)
michael@0 1043 if loopPoint:
michael@0 1044 return loopPoint
michael@0 1045 if otherInterface in self.implementedInterfaces:
michael@0 1046 return self
michael@0 1047 for iface in self.implementedInterfaces:
michael@0 1048 loopPoint = iface.findInterfaceLoopPoint(otherInterface)
michael@0 1049 if loopPoint:
michael@0 1050 return loopPoint
michael@0 1051 return None
michael@0 1052
michael@0 1053 def getExtendedAttribute(self, name):
michael@0 1054 return self._extendedAttrDict.get(name, None)
michael@0 1055
michael@0 1056 def setNonPartial(self, location, parent, members):
michael@0 1057 assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
michael@0 1058 if not self._isPartial:
michael@0 1059 raise WebIDLError("Two non-partial definitions for the "
michael@0 1060 "same interface",
michael@0 1061 [location, self.location])
michael@0 1062 self._isPartial = False
michael@0 1063 # Now make it look like we were parsed at this new location, since
michael@0 1064 # that's the place where the interface is "really" defined
michael@0 1065 self.location = location
michael@0 1066 assert not self.parent
michael@0 1067 self.parent = parent
michael@0 1068 # Put the new members at the beginning
michael@0 1069 self.members = members + self.members
michael@0 1070
michael@0 1071 def getJSImplementation(self):
michael@0 1072 classId = self.getExtendedAttribute("JSImplementation")
michael@0 1073 if not classId:
michael@0 1074 return classId
michael@0 1075 assert isinstance(classId, list)
michael@0 1076 assert len(classId) == 1
michael@0 1077 return classId[0]
michael@0 1078
michael@0 1079 def isJSImplemented(self):
michael@0 1080 return bool(self.getJSImplementation())
michael@0 1081
michael@0 1082 def getNavigatorProperty(self):
michael@0 1083 naviProp = self.getExtendedAttribute("NavigatorProperty")
michael@0 1084 if not naviProp:
michael@0 1085 return None
michael@0 1086 assert len(naviProp) == 1
michael@0 1087 assert isinstance(naviProp, list)
michael@0 1088 assert len(naviProp[0]) != 0
michael@0 1089 return naviProp[0]
michael@0 1090
michael@0 1091 def hasChildInterfaces(self):
michael@0 1092 return self._hasChildInterfaces
michael@0 1093
michael@0 1094 def isOnGlobalProtoChain(self):
michael@0 1095 return self._isOnGlobalProtoChain
michael@0 1096
michael@0 1097 def _getDependentObjects(self):
michael@0 1098 deps = set(self.members)
michael@0 1099 deps.union(self.implementedInterfaces)
michael@0 1100 if self.parent:
michael@0 1101 deps.add(self.parent)
michael@0 1102 return deps
michael@0 1103
michael@0 1104 def hasMembersInSlots(self):
michael@0 1105 return self._ownMembersInSlots != 0
michael@0 1106
michael@0 1107 class IDLDictionary(IDLObjectWithScope):
michael@0 1108 def __init__(self, location, parentScope, name, parent, members):
michael@0 1109 assert isinstance(parentScope, IDLScope)
michael@0 1110 assert isinstance(name, IDLUnresolvedIdentifier)
michael@0 1111 assert not parent or isinstance(parent, IDLIdentifierPlaceholder)
michael@0 1112
michael@0 1113 self.parent = parent
michael@0 1114 self._finished = False
michael@0 1115 self.members = list(members)
michael@0 1116
michael@0 1117 IDLObjectWithScope.__init__(self, location, parentScope, name)
michael@0 1118
michael@0 1119 def __str__(self):
michael@0 1120 return "Dictionary '%s'" % self.identifier.name
michael@0 1121
michael@0 1122 def isDictionary(self):
michael@0 1123 return True;
michael@0 1124
michael@0 1125 def finish(self, scope):
michael@0 1126 if self._finished:
michael@0 1127 return
michael@0 1128
michael@0 1129 self._finished = True
michael@0 1130
michael@0 1131 if self.parent:
michael@0 1132 assert isinstance(self.parent, IDLIdentifierPlaceholder)
michael@0 1133 oldParent = self.parent
michael@0 1134 self.parent = self.parent.finish(scope)
michael@0 1135 if not isinstance(self.parent, IDLDictionary):
michael@0 1136 raise WebIDLError("Dictionary %s has parent that is not a dictionary" %
michael@0 1137 self.identifier.name,
michael@0 1138 [oldParent.location, self.parent.location])
michael@0 1139
michael@0 1140 # Make sure the parent resolves all its members before we start
michael@0 1141 # looking at them.
michael@0 1142 self.parent.finish(scope)
michael@0 1143
michael@0 1144 for member in self.members:
michael@0 1145 member.resolve(self)
michael@0 1146 if not member.isComplete():
michael@0 1147 member.complete(scope)
michael@0 1148 assert member.type.isComplete()
michael@0 1149
michael@0 1150 # Members of a dictionary are sorted in lexicographic order
michael@0 1151 self.members.sort(cmp=cmp, key=lambda x: x.identifier.name)
michael@0 1152
michael@0 1153 inheritedMembers = []
michael@0 1154 ancestor = self.parent
michael@0 1155 while ancestor:
michael@0 1156 if ancestor == self:
michael@0 1157 raise WebIDLError("Dictionary %s has itself as an ancestor" %
michael@0 1158 self.identifier.name,
michael@0 1159 [self.identifier.location])
michael@0 1160 inheritedMembers.extend(ancestor.members)
michael@0 1161 ancestor = ancestor.parent
michael@0 1162
michael@0 1163 # Catch name duplication
michael@0 1164 for inheritedMember in inheritedMembers:
michael@0 1165 for member in self.members:
michael@0 1166 if member.identifier.name == inheritedMember.identifier.name:
michael@0 1167 raise WebIDLError("Dictionary %s has two members with name %s" %
michael@0 1168 (self.identifier.name, member.identifier.name),
michael@0 1169 [member.location, inheritedMember.location])
michael@0 1170
michael@0 1171 def validate(self):
michael@0 1172 def typeContainsDictionary(memberType, dictionary):
michael@0 1173 """
michael@0 1174 Returns a tuple whose:
michael@0 1175
michael@0 1176 - First element is a Boolean value indicating whether
michael@0 1177 memberType contains dictionary.
michael@0 1178
michael@0 1179 - Second element is:
michael@0 1180 A list of locations that leads from the type that was passed in
michael@0 1181 the memberType argument, to the dictionary being validated,
michael@0 1182 if the boolean value in the first element is True.
michael@0 1183
michael@0 1184 None, if the boolean value in the first element is False.
michael@0 1185 """
michael@0 1186
michael@0 1187 if (memberType.nullable() or
michael@0 1188 memberType.isArray() or
michael@0 1189 memberType.isSequence() or
michael@0 1190 memberType.isMozMap()):
michael@0 1191 return typeContainsDictionary(memberType.inner, dictionary)
michael@0 1192
michael@0 1193 if memberType.isDictionary():
michael@0 1194 if memberType.inner == dictionary:
michael@0 1195 return (True, [memberType.location])
michael@0 1196
michael@0 1197 (contains, locations) = dictionaryContainsDictionary(memberType.inner, \
michael@0 1198 dictionary)
michael@0 1199 if contains:
michael@0 1200 return (True, [memberType.location] + locations)
michael@0 1201
michael@0 1202 if memberType.isUnion():
michael@0 1203 for member in memberType.flatMemberTypes:
michael@0 1204 (contains, locations) = typeContainsDictionary(member, dictionary)
michael@0 1205 if contains:
michael@0 1206 return (True, locations)
michael@0 1207
michael@0 1208 return (False, None)
michael@0 1209
michael@0 1210 def dictionaryContainsDictionary(dictMember, dictionary):
michael@0 1211 for member in dictMember.members:
michael@0 1212 (contains, locations) = typeContainsDictionary(member.type, dictionary)
michael@0 1213 if contains:
michael@0 1214 return (True, [member.location] + locations)
michael@0 1215
michael@0 1216 if dictMember.parent:
michael@0 1217 if dictMember.parent == dictionary:
michael@0 1218 return (True, [dictMember.location])
michael@0 1219 else:
michael@0 1220 (contains, locations) = dictionaryContainsDictionary(dictMember.parent, dictionary)
michael@0 1221 if contains:
michael@0 1222 return (True, [dictMember.location] + locations)
michael@0 1223
michael@0 1224 return (False, None)
michael@0 1225
michael@0 1226 for member in self.members:
michael@0 1227 if member.type.isDictionary() and member.type.nullable():
michael@0 1228 raise WebIDLError("Dictionary %s has member with nullable "
michael@0 1229 "dictionary type" % self.identifier.name,
michael@0 1230 [member.location])
michael@0 1231 (contains, locations) = typeContainsDictionary(member.type, self)
michael@0 1232 if contains:
michael@0 1233 raise WebIDLError("Dictionary %s has member with itself as type." %
michael@0 1234 self.identifier.name,
michael@0 1235 [member.location] + locations)
michael@0 1236
michael@0 1237 def addExtendedAttributes(self, attrs):
michael@0 1238 assert len(attrs) == 0
michael@0 1239
michael@0 1240 def _getDependentObjects(self):
michael@0 1241 deps = set(self.members)
michael@0 1242 if (self.parent):
michael@0 1243 deps.add(self.parent)
michael@0 1244 return deps
michael@0 1245
michael@0 1246 class IDLEnum(IDLObjectWithIdentifier):
michael@0 1247 def __init__(self, location, parentScope, name, values):
michael@0 1248 assert isinstance(parentScope, IDLScope)
michael@0 1249 assert isinstance(name, IDLUnresolvedIdentifier)
michael@0 1250
michael@0 1251 if len(values) != len(set(values)):
michael@0 1252 raise WebIDLError("Enum %s has multiple identical strings" % name.name,
michael@0 1253 [location])
michael@0 1254
michael@0 1255 IDLObjectWithIdentifier.__init__(self, location, parentScope, name)
michael@0 1256 self._values = values
michael@0 1257
michael@0 1258 def values(self):
michael@0 1259 return self._values
michael@0 1260
michael@0 1261 def finish(self, scope):
michael@0 1262 pass
michael@0 1263
michael@0 1264 def validate(self):
michael@0 1265 pass
michael@0 1266
michael@0 1267 def isEnum(self):
michael@0 1268 return True
michael@0 1269
michael@0 1270 def addExtendedAttributes(self, attrs):
michael@0 1271 assert len(attrs) == 0
michael@0 1272
michael@0 1273 def _getDependentObjects(self):
michael@0 1274 return set()
michael@0 1275
michael@0 1276 class IDLType(IDLObject):
michael@0 1277 Tags = enum(
michael@0 1278 # The integer types
michael@0 1279 'int8',
michael@0 1280 'uint8',
michael@0 1281 'int16',
michael@0 1282 'uint16',
michael@0 1283 'int32',
michael@0 1284 'uint32',
michael@0 1285 'int64',
michael@0 1286 'uint64',
michael@0 1287 # Additional primitive types
michael@0 1288 'bool',
michael@0 1289 'unrestricted_float',
michael@0 1290 'float',
michael@0 1291 'unrestricted_double',
michael@0 1292 # "double" last primitive type to match IDLBuiltinType
michael@0 1293 'double',
michael@0 1294 # Other types
michael@0 1295 'any',
michael@0 1296 'domstring',
michael@0 1297 'bytestring',
michael@0 1298 'object',
michael@0 1299 'date',
michael@0 1300 'void',
michael@0 1301 # Funny stuff
michael@0 1302 'interface',
michael@0 1303 'dictionary',
michael@0 1304 'enum',
michael@0 1305 'callback',
michael@0 1306 'union',
michael@0 1307 'sequence',
michael@0 1308 'mozmap',
michael@0 1309 'array'
michael@0 1310 )
michael@0 1311
michael@0 1312 def __init__(self, location, name):
michael@0 1313 IDLObject.__init__(self, location)
michael@0 1314 self.name = name
michael@0 1315 self.builtin = False
michael@0 1316
michael@0 1317 def __eq__(self, other):
michael@0 1318 return other and self.builtin == other.builtin and self.name == other.name
michael@0 1319
michael@0 1320 def __ne__(self, other):
michael@0 1321 return not self == other
michael@0 1322
michael@0 1323 def __str__(self):
michael@0 1324 return str(self.name)
michael@0 1325
michael@0 1326 def isType(self):
michael@0 1327 return True
michael@0 1328
michael@0 1329 def nullable(self):
michael@0 1330 return False
michael@0 1331
michael@0 1332 def isPrimitive(self):
michael@0 1333 return False
michael@0 1334
michael@0 1335 def isBoolean(self):
michael@0 1336 return False
michael@0 1337
michael@0 1338 def isNumeric(self):
michael@0 1339 return False
michael@0 1340
michael@0 1341 def isString(self):
michael@0 1342 return False
michael@0 1343
michael@0 1344 def isByteString(self):
michael@0 1345 return False
michael@0 1346
michael@0 1347 def isDOMString(self):
michael@0 1348 return False
michael@0 1349
michael@0 1350 def isVoid(self):
michael@0 1351 return self.name == "Void"
michael@0 1352
michael@0 1353 def isSequence(self):
michael@0 1354 return False
michael@0 1355
michael@0 1356 def isMozMap(self):
michael@0 1357 return False
michael@0 1358
michael@0 1359 def isArray(self):
michael@0 1360 return False
michael@0 1361
michael@0 1362 def isArrayBuffer(self):
michael@0 1363 return False
michael@0 1364
michael@0 1365 def isArrayBufferView(self):
michael@0 1366 return False
michael@0 1367
michael@0 1368 def isTypedArray(self):
michael@0 1369 return False
michael@0 1370
michael@0 1371 def isCallbackInterface(self):
michael@0 1372 return False
michael@0 1373
michael@0 1374 def isNonCallbackInterface(self):
michael@0 1375 return False
michael@0 1376
michael@0 1377 def isGeckoInterface(self):
michael@0 1378 """ Returns a boolean indicating whether this type is an 'interface'
michael@0 1379 type that is implemented in Gecko. At the moment, this returns
michael@0 1380 true for all interface types that are not types from the TypedArray
michael@0 1381 spec."""
michael@0 1382 return self.isInterface() and not self.isSpiderMonkeyInterface()
michael@0 1383
michael@0 1384 def isSpiderMonkeyInterface(self):
michael@0 1385 """ Returns a boolean indicating whether this type is an 'interface'
michael@0 1386 type that is implemented in Spidermonkey. At the moment, this
michael@0 1387 only returns true for the types from the TypedArray spec. """
michael@0 1388 return self.isInterface() and (self.isArrayBuffer() or \
michael@0 1389 self.isArrayBufferView() or \
michael@0 1390 self.isTypedArray())
michael@0 1391
michael@0 1392 def isDictionary(self):
michael@0 1393 return False
michael@0 1394
michael@0 1395 def isInterface(self):
michael@0 1396 return False
michael@0 1397
michael@0 1398 def isAny(self):
michael@0 1399 return self.tag() == IDLType.Tags.any
michael@0 1400
michael@0 1401 def isDate(self):
michael@0 1402 return self.tag() == IDLType.Tags.date
michael@0 1403
michael@0 1404 def isObject(self):
michael@0 1405 return self.tag() == IDLType.Tags.object
michael@0 1406
michael@0 1407 def isPromise(self):
michael@0 1408 return False
michael@0 1409
michael@0 1410 def isComplete(self):
michael@0 1411 return True
michael@0 1412
michael@0 1413 def includesRestrictedFloat(self):
michael@0 1414 return False
michael@0 1415
michael@0 1416 def isFloat(self):
michael@0 1417 return False
michael@0 1418
michael@0 1419 def isUnrestricted(self):
michael@0 1420 # Should only call this on float types
michael@0 1421 assert self.isFloat()
michael@0 1422
michael@0 1423 def isSerializable(self):
michael@0 1424 return False
michael@0 1425
michael@0 1426 def tag(self):
michael@0 1427 assert False # Override me!
michael@0 1428
michael@0 1429 def treatNonCallableAsNull(self):
michael@0 1430 assert self.tag() == IDLType.Tags.callback
michael@0 1431 return self.nullable() and self.inner._treatNonCallableAsNull
michael@0 1432
michael@0 1433 def treatNonObjectAsNull(self):
michael@0 1434 assert self.tag() == IDLType.Tags.callback
michael@0 1435 return self.nullable() and self.inner._treatNonObjectAsNull
michael@0 1436
michael@0 1437 def addExtendedAttributes(self, attrs):
michael@0 1438 assert len(attrs) == 0
michael@0 1439
michael@0 1440 def resolveType(self, parentScope):
michael@0 1441 pass
michael@0 1442
michael@0 1443 def unroll(self):
michael@0 1444 return self
michael@0 1445
michael@0 1446 def isDistinguishableFrom(self, other):
michael@0 1447 raise TypeError("Can't tell whether a generic type is or is not "
michael@0 1448 "distinguishable from other things")
michael@0 1449
michael@0 1450 class IDLUnresolvedType(IDLType):
michael@0 1451 """
michael@0 1452 Unresolved types are interface types
michael@0 1453 """
michael@0 1454
michael@0 1455 def __init__(self, location, name):
michael@0 1456 IDLType.__init__(self, location, name)
michael@0 1457
michael@0 1458 def isComplete(self):
michael@0 1459 return False
michael@0 1460
michael@0 1461 def complete(self, scope):
michael@0 1462 obj = None
michael@0 1463 try:
michael@0 1464 obj = scope._lookupIdentifier(self.name)
michael@0 1465 except:
michael@0 1466 raise WebIDLError("Unresolved type '%s'." % self.name,
michael@0 1467 [self.location])
michael@0 1468
michael@0 1469 assert obj
michael@0 1470 if obj.isType():
michael@0 1471 # obj itself might not be complete; deal with that.
michael@0 1472 assert obj != self
michael@0 1473 if not obj.isComplete():
michael@0 1474 obj = obj.complete(scope)
michael@0 1475 return obj
michael@0 1476
michael@0 1477 name = self.name.resolve(scope, None)
michael@0 1478 return IDLWrapperType(self.location, obj)
michael@0 1479
michael@0 1480 def isDistinguishableFrom(self, other):
michael@0 1481 raise TypeError("Can't tell whether an unresolved type is or is not "
michael@0 1482 "distinguishable from other things")
michael@0 1483
michael@0 1484 class IDLNullableType(IDLType):
michael@0 1485 def __init__(self, location, innerType):
michael@0 1486 assert not innerType.isVoid()
michael@0 1487 assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any]
michael@0 1488
michael@0 1489 IDLType.__init__(self, location, innerType.name)
michael@0 1490 self.inner = innerType
michael@0 1491 self.builtin = False
michael@0 1492
michael@0 1493 def __eq__(self, other):
michael@0 1494 return isinstance(other, IDLNullableType) and self.inner == other.inner
michael@0 1495
michael@0 1496 def __str__(self):
michael@0 1497 return self.inner.__str__() + "OrNull"
michael@0 1498
michael@0 1499 def nullable(self):
michael@0 1500 return True
michael@0 1501
michael@0 1502 def isCallback(self):
michael@0 1503 return self.inner.isCallback()
michael@0 1504
michael@0 1505 def isPrimitive(self):
michael@0 1506 return self.inner.isPrimitive()
michael@0 1507
michael@0 1508 def isBoolean(self):
michael@0 1509 return self.inner.isBoolean()
michael@0 1510
michael@0 1511 def isNumeric(self):
michael@0 1512 return self.inner.isNumeric()
michael@0 1513
michael@0 1514 def isString(self):
michael@0 1515 return self.inner.isString()
michael@0 1516
michael@0 1517 def isByteString(self):
michael@0 1518 return self.inner.isByteString()
michael@0 1519
michael@0 1520 def isDOMString(self):
michael@0 1521 return self.inner.isDOMString()
michael@0 1522
michael@0 1523 def isFloat(self):
michael@0 1524 return self.inner.isFloat()
michael@0 1525
michael@0 1526 def isUnrestricted(self):
michael@0 1527 return self.inner.isUnrestricted()
michael@0 1528
michael@0 1529 def includesRestrictedFloat(self):
michael@0 1530 return self.inner.includesRestrictedFloat()
michael@0 1531
michael@0 1532 def isInteger(self):
michael@0 1533 return self.inner.isInteger()
michael@0 1534
michael@0 1535 def isVoid(self):
michael@0 1536 return False
michael@0 1537
michael@0 1538 def isSequence(self):
michael@0 1539 return self.inner.isSequence()
michael@0 1540
michael@0 1541 def isMozMap(self):
michael@0 1542 return self.inner.isMozMap()
michael@0 1543
michael@0 1544 def isArray(self):
michael@0 1545 return self.inner.isArray()
michael@0 1546
michael@0 1547 def isArrayBuffer(self):
michael@0 1548 return self.inner.isArrayBuffer()
michael@0 1549
michael@0 1550 def isArrayBufferView(self):
michael@0 1551 return self.inner.isArrayBufferView()
michael@0 1552
michael@0 1553 def isTypedArray(self):
michael@0 1554 return self.inner.isTypedArray()
michael@0 1555
michael@0 1556 def isDictionary(self):
michael@0 1557 return self.inner.isDictionary()
michael@0 1558
michael@0 1559 def isInterface(self):
michael@0 1560 return self.inner.isInterface()
michael@0 1561
michael@0 1562 def isCallbackInterface(self):
michael@0 1563 return self.inner.isCallbackInterface()
michael@0 1564
michael@0 1565 def isNonCallbackInterface(self):
michael@0 1566 return self.inner.isNonCallbackInterface()
michael@0 1567
michael@0 1568 def isEnum(self):
michael@0 1569 return self.inner.isEnum()
michael@0 1570
michael@0 1571 def isUnion(self):
michael@0 1572 return self.inner.isUnion()
michael@0 1573
michael@0 1574 def isSerializable(self):
michael@0 1575 return self.inner.isSerializable()
michael@0 1576
michael@0 1577 def tag(self):
michael@0 1578 return self.inner.tag()
michael@0 1579
michael@0 1580 def resolveType(self, parentScope):
michael@0 1581 assert isinstance(parentScope, IDLScope)
michael@0 1582 self.inner.resolveType(parentScope)
michael@0 1583
michael@0 1584 def isComplete(self):
michael@0 1585 return self.inner.isComplete()
michael@0 1586
michael@0 1587 def complete(self, scope):
michael@0 1588 self.inner = self.inner.complete(scope)
michael@0 1589 if self.inner.nullable():
michael@0 1590 raise WebIDLError("The inner type of a nullable type must not be "
michael@0 1591 "a nullable type",
michael@0 1592 [self.location, self.inner.location])
michael@0 1593 if self.inner.isUnion():
michael@0 1594 if self.inner.hasNullableType:
michael@0 1595 raise WebIDLError("The inner type of a nullable type must not "
michael@0 1596 "be a union type that itself has a nullable "
michael@0 1597 "type as a member type", [self.location])
michael@0 1598
michael@0 1599 self.name = self.inner.name
michael@0 1600 return self
michael@0 1601
michael@0 1602 def unroll(self):
michael@0 1603 return self.inner.unroll()
michael@0 1604
michael@0 1605 def isDistinguishableFrom(self, other):
michael@0 1606 if (other.nullable() or (other.isUnion() and other.hasNullableType) or
michael@0 1607 other.isDictionary()):
michael@0 1608 # Can't tell which type null should become
michael@0 1609 return False
michael@0 1610 return self.inner.isDistinguishableFrom(other)
michael@0 1611
michael@0 1612 def _getDependentObjects(self):
michael@0 1613 return self.inner._getDependentObjects()
michael@0 1614
michael@0 1615 class IDLSequenceType(IDLType):
michael@0 1616 def __init__(self, location, parameterType):
michael@0 1617 assert not parameterType.isVoid()
michael@0 1618
michael@0 1619 IDLType.__init__(self, location, parameterType.name)
michael@0 1620 self.inner = parameterType
michael@0 1621 self.builtin = False
michael@0 1622
michael@0 1623 def __eq__(self, other):
michael@0 1624 return isinstance(other, IDLSequenceType) and self.inner == other.inner
michael@0 1625
michael@0 1626 def __str__(self):
michael@0 1627 return self.inner.__str__() + "Sequence"
michael@0 1628
michael@0 1629 def nullable(self):
michael@0 1630 return False
michael@0 1631
michael@0 1632 def isPrimitive(self):
michael@0 1633 return False;
michael@0 1634
michael@0 1635 def isString(self):
michael@0 1636 return False;
michael@0 1637
michael@0 1638 def isByteString(self):
michael@0 1639 return False
michael@0 1640
michael@0 1641 def isDOMString(self):
michael@0 1642 return False
michael@0 1643
michael@0 1644 def isVoid(self):
michael@0 1645 return False
michael@0 1646
michael@0 1647 def isSequence(self):
michael@0 1648 return True
michael@0 1649
michael@0 1650 def isArray(self):
michael@0 1651 return False
michael@0 1652
michael@0 1653 def isDictionary(self):
michael@0 1654 return False
michael@0 1655
michael@0 1656 def isInterface(self):
michael@0 1657 return False
michael@0 1658
michael@0 1659 def isEnum(self):
michael@0 1660 return False
michael@0 1661
michael@0 1662 def isSerializable(self):
michael@0 1663 return self.inner.isSerializable()
michael@0 1664
michael@0 1665 def includesRestrictedFloat(self):
michael@0 1666 return self.inner.includesRestrictedFloat()
michael@0 1667
michael@0 1668 def tag(self):
michael@0 1669 return IDLType.Tags.sequence
michael@0 1670
michael@0 1671 def resolveType(self, parentScope):
michael@0 1672 assert isinstance(parentScope, IDLScope)
michael@0 1673 self.inner.resolveType(parentScope)
michael@0 1674
michael@0 1675 def isComplete(self):
michael@0 1676 return self.inner.isComplete()
michael@0 1677
michael@0 1678 def complete(self, scope):
michael@0 1679 self.inner = self.inner.complete(scope)
michael@0 1680 self.name = self.inner.name
michael@0 1681 return self
michael@0 1682
michael@0 1683 def unroll(self):
michael@0 1684 return self.inner.unroll()
michael@0 1685
michael@0 1686 def isDistinguishableFrom(self, other):
michael@0 1687 if other.isUnion():
michael@0 1688 # Just forward to the union; it'll deal
michael@0 1689 return other.isDistinguishableFrom(self)
michael@0 1690 return (other.isPrimitive() or other.isString() or other.isEnum() or
michael@0 1691 other.isDate() or other.isNonCallbackInterface())
michael@0 1692
michael@0 1693 def _getDependentObjects(self):
michael@0 1694 return self.inner._getDependentObjects()
michael@0 1695
michael@0 1696 class IDLMozMapType(IDLType):
michael@0 1697 # XXXbz This is pretty similar to IDLSequenceType in various ways.
michael@0 1698 # And maybe to IDLNullableType. Should we have a superclass for
michael@0 1699 # "type containing this other type"? Bug 1015318.
michael@0 1700 def __init__(self, location, parameterType):
michael@0 1701 assert not parameterType.isVoid()
michael@0 1702
michael@0 1703 IDLType.__init__(self, location, parameterType.name)
michael@0 1704 self.inner = parameterType
michael@0 1705 self.builtin = False
michael@0 1706
michael@0 1707 def __eq__(self, other):
michael@0 1708 return isinstance(other, IDLMozMapType) and self.inner == other.inner
michael@0 1709
michael@0 1710 def __str__(self):
michael@0 1711 return self.inner.__str__() + "MozMap"
michael@0 1712
michael@0 1713 def isMozMap(self):
michael@0 1714 return True
michael@0 1715
michael@0 1716 def includesRestrictedFloat(self):
michael@0 1717 return self.inner.includesRestrictedFloat()
michael@0 1718
michael@0 1719 def tag(self):
michael@0 1720 return IDLType.Tags.mozmap
michael@0 1721
michael@0 1722 def resolveType(self, parentScope):
michael@0 1723 assert isinstance(parentScope, IDLScope)
michael@0 1724 self.inner.resolveType(parentScope)
michael@0 1725
michael@0 1726 def isComplete(self):
michael@0 1727 return self.inner.isComplete()
michael@0 1728
michael@0 1729 def complete(self, scope):
michael@0 1730 self.inner = self.inner.complete(scope)
michael@0 1731 self.name = self.inner.name
michael@0 1732 return self
michael@0 1733
michael@0 1734 def unroll(self):
michael@0 1735 # We do not unroll our inner. Just stop at ourselves. That
michael@0 1736 # lets us add headers for both ourselves and our inner as
michael@0 1737 # needed.
michael@0 1738 return self
michael@0 1739
michael@0 1740 def isDistinguishableFrom(self, other):
michael@0 1741 if other.isUnion():
michael@0 1742 # Just forward to the union; it'll deal
michael@0 1743 return other.isDistinguishableFrom(self)
michael@0 1744 return (other.isPrimitive() or other.isString() or other.isEnum() or
michael@0 1745 other.isDate() or other.isNonCallbackInterface())
michael@0 1746
michael@0 1747 def _getDependentObjects(self):
michael@0 1748 return self.inner._getDependentObjects()
michael@0 1749
michael@0 1750 class IDLUnionType(IDLType):
michael@0 1751 def __init__(self, location, memberTypes):
michael@0 1752 IDLType.__init__(self, location, "")
michael@0 1753 self.memberTypes = memberTypes
michael@0 1754 self.hasNullableType = False
michael@0 1755 self.hasDictionaryType = False
michael@0 1756 self.flatMemberTypes = None
michael@0 1757 self.builtin = False
michael@0 1758
michael@0 1759 def __eq__(self, other):
michael@0 1760 return isinstance(other, IDLUnionType) and self.memberTypes == other.memberTypes
michael@0 1761
michael@0 1762 def isVoid(self):
michael@0 1763 return False
michael@0 1764
michael@0 1765 def isUnion(self):
michael@0 1766 return True
michael@0 1767
michael@0 1768 def isSerializable(self):
michael@0 1769 return all(m.isSerializable() for m in self.memberTypes)
michael@0 1770
michael@0 1771 def includesRestrictedFloat(self):
michael@0 1772 return any(t.includesRestrictedFloat() for t in self.memberTypes)
michael@0 1773
michael@0 1774 def tag(self):
michael@0 1775 return IDLType.Tags.union
michael@0 1776
michael@0 1777 def resolveType(self, parentScope):
michael@0 1778 assert isinstance(parentScope, IDLScope)
michael@0 1779 for t in self.memberTypes:
michael@0 1780 t.resolveType(parentScope)
michael@0 1781
michael@0 1782 def isComplete(self):
michael@0 1783 return self.flatMemberTypes is not None
michael@0 1784
michael@0 1785 def complete(self, scope):
michael@0 1786 def typeName(type):
michael@0 1787 if isinstance(type, IDLNullableType):
michael@0 1788 return typeName(type.inner) + "OrNull"
michael@0 1789 if isinstance(type, IDLWrapperType):
michael@0 1790 return typeName(type._identifier.object())
michael@0 1791 if isinstance(type, IDLObjectWithIdentifier):
michael@0 1792 return typeName(type.identifier)
michael@0 1793 if (isinstance(type, IDLType) and
michael@0 1794 (type.isArray() or type.isSequence() or type.isMozMap)):
michael@0 1795 return str(type)
michael@0 1796 return type.name
michael@0 1797
michael@0 1798 for (i, type) in enumerate(self.memberTypes):
michael@0 1799 if not type.isComplete():
michael@0 1800 self.memberTypes[i] = type.complete(scope)
michael@0 1801
michael@0 1802 self.name = "Or".join(typeName(type) for type in self.memberTypes)
michael@0 1803 self.flatMemberTypes = list(self.memberTypes)
michael@0 1804 i = 0
michael@0 1805 while i < len(self.flatMemberTypes):
michael@0 1806 if self.flatMemberTypes[i].nullable():
michael@0 1807 if self.hasNullableType:
michael@0 1808 raise WebIDLError("Can't have more than one nullable types in a union",
michael@0 1809 [nullableType.location, self.flatMemberTypes[i].location])
michael@0 1810 if self.hasDictionaryType:
michael@0 1811 raise WebIDLError("Can't have a nullable type and a "
michael@0 1812 "dictionary type in a union",
michael@0 1813 [dictionaryType.location,
michael@0 1814 self.flatMemberTypes[i].location])
michael@0 1815 self.hasNullableType = True
michael@0 1816 nullableType = self.flatMemberTypes[i]
michael@0 1817 self.flatMemberTypes[i] = self.flatMemberTypes[i].inner
michael@0 1818 continue
michael@0 1819 if self.flatMemberTypes[i].isDictionary():
michael@0 1820 if self.hasNullableType:
michael@0 1821 raise WebIDLError("Can't have a nullable type and a "
michael@0 1822 "dictionary type in a union",
michael@0 1823 [nullableType.location,
michael@0 1824 self.flatMemberTypes[i].location])
michael@0 1825 self.hasDictionaryType = True
michael@0 1826 dictionaryType = self.flatMemberTypes[i]
michael@0 1827 elif self.flatMemberTypes[i].isUnion():
michael@0 1828 self.flatMemberTypes[i:i + 1] = self.flatMemberTypes[i].memberTypes
michael@0 1829 continue
michael@0 1830 i += 1
michael@0 1831
michael@0 1832 for (i, t) in enumerate(self.flatMemberTypes[:-1]):
michael@0 1833 for u in self.flatMemberTypes[i + 1:]:
michael@0 1834 if not t.isDistinguishableFrom(u):
michael@0 1835 raise WebIDLError("Flat member types of a union should be "
michael@0 1836 "distinguishable, " + str(t) + " is not "
michael@0 1837 "distinguishable from " + str(u),
michael@0 1838 [self.location, t.location, u.location])
michael@0 1839
michael@0 1840 return self
michael@0 1841
michael@0 1842 def isDistinguishableFrom(self, other):
michael@0 1843 if self.hasNullableType and other.nullable():
michael@0 1844 # Can't tell which type null should become
michael@0 1845 return False
michael@0 1846 if other.isUnion():
michael@0 1847 otherTypes = other.unroll().memberTypes
michael@0 1848 else:
michael@0 1849 otherTypes = [other]
michael@0 1850 # For every type in otherTypes, check that it's distinguishable from
michael@0 1851 # every type in our types
michael@0 1852 for u in otherTypes:
michael@0 1853 if any(not t.isDistinguishableFrom(u) for t in self.memberTypes):
michael@0 1854 return False
michael@0 1855 return True
michael@0 1856
michael@0 1857 def _getDependentObjects(self):
michael@0 1858 return set(self.memberTypes)
michael@0 1859
michael@0 1860 class IDLArrayType(IDLType):
michael@0 1861 def __init__(self, location, parameterType):
michael@0 1862 assert not parameterType.isVoid()
michael@0 1863 if parameterType.isSequence():
michael@0 1864 raise WebIDLError("Array type cannot parameterize over a sequence type",
michael@0 1865 [location])
michael@0 1866 if parameterType.isMozMap():
michael@0 1867 raise WebIDLError("Array type cannot parameterize over a MozMap type",
michael@0 1868 [location])
michael@0 1869 if parameterType.isDictionary():
michael@0 1870 raise WebIDLError("Array type cannot parameterize over a dictionary type",
michael@0 1871 [location])
michael@0 1872
michael@0 1873 IDLType.__init__(self, location, parameterType.name)
michael@0 1874 self.inner = parameterType
michael@0 1875 self.builtin = False
michael@0 1876
michael@0 1877 def __eq__(self, other):
michael@0 1878 return isinstance(other, IDLArrayType) and self.inner == other.inner
michael@0 1879
michael@0 1880 def __str__(self):
michael@0 1881 return self.inner.__str__() + "Array"
michael@0 1882
michael@0 1883 def nullable(self):
michael@0 1884 return False
michael@0 1885
michael@0 1886 def isPrimitive(self):
michael@0 1887 return False
michael@0 1888
michael@0 1889 def isString(self):
michael@0 1890 return False
michael@0 1891
michael@0 1892 def isByteString(self):
michael@0 1893 return False
michael@0 1894
michael@0 1895 def isDOMString(self):
michael@0 1896 return False
michael@0 1897
michael@0 1898 def isVoid(self):
michael@0 1899 return False
michael@0 1900
michael@0 1901 def isSequence(self):
michael@0 1902 assert not self.inner.isSequence()
michael@0 1903 return False
michael@0 1904
michael@0 1905 def isArray(self):
michael@0 1906 return True
michael@0 1907
michael@0 1908 def isDictionary(self):
michael@0 1909 assert not self.inner.isDictionary()
michael@0 1910 return False
michael@0 1911
michael@0 1912 def isInterface(self):
michael@0 1913 return False
michael@0 1914
michael@0 1915 def isEnum(self):
michael@0 1916 return False
michael@0 1917
michael@0 1918 def tag(self):
michael@0 1919 return IDLType.Tags.array
michael@0 1920
michael@0 1921 def resolveType(self, parentScope):
michael@0 1922 assert isinstance(parentScope, IDLScope)
michael@0 1923 self.inner.resolveType(parentScope)
michael@0 1924
michael@0 1925 def isComplete(self):
michael@0 1926 return self.inner.isComplete()
michael@0 1927
michael@0 1928 def complete(self, scope):
michael@0 1929 self.inner = self.inner.complete(scope)
michael@0 1930 self.name = self.inner.name
michael@0 1931
michael@0 1932 if self.inner.isDictionary():
michael@0 1933 raise WebIDLError("Array type must not contain "
michael@0 1934 "dictionary as element type.",
michael@0 1935 [self.inner.location])
michael@0 1936
michael@0 1937 assert not self.inner.isSequence()
michael@0 1938
michael@0 1939 return self
michael@0 1940
michael@0 1941 def unroll(self):
michael@0 1942 return self.inner.unroll()
michael@0 1943
michael@0 1944 def isDistinguishableFrom(self, other):
michael@0 1945 if other.isUnion():
michael@0 1946 # Just forward to the union; it'll deal
michael@0 1947 return other.isDistinguishableFrom(self)
michael@0 1948 return (other.isPrimitive() or other.isString() or other.isEnum() or
michael@0 1949 other.isDate() or other.isNonCallbackInterface())
michael@0 1950
michael@0 1951 def _getDependentObjects(self):
michael@0 1952 return self.inner._getDependentObjects()
michael@0 1953
michael@0 1954 class IDLTypedefType(IDLType, IDLObjectWithIdentifier):
michael@0 1955 def __init__(self, location, innerType, name):
michael@0 1956 IDLType.__init__(self, location, innerType.name)
michael@0 1957
michael@0 1958 identifier = IDLUnresolvedIdentifier(location, name)
michael@0 1959
michael@0 1960 IDLObjectWithIdentifier.__init__(self, location, None, identifier)
michael@0 1961
michael@0 1962 self.inner = innerType
michael@0 1963 self.name = name
michael@0 1964 self.builtin = False
michael@0 1965
michael@0 1966 def __eq__(self, other):
michael@0 1967 return isinstance(other, IDLTypedefType) and self.inner == other.inner
michael@0 1968
michael@0 1969 def __str__(self):
michael@0 1970 return self.identifier.name
michael@0 1971
michael@0 1972 def nullable(self):
michael@0 1973 return self.inner.nullable()
michael@0 1974
michael@0 1975 def isPrimitive(self):
michael@0 1976 return self.inner.isPrimitive()
michael@0 1977
michael@0 1978 def isBoolean(self):
michael@0 1979 return self.inner.isBoolean()
michael@0 1980
michael@0 1981 def isNumeric(self):
michael@0 1982 return self.inner.isNumeric()
michael@0 1983
michael@0 1984 def isString(self):
michael@0 1985 return self.inner.isString()
michael@0 1986
michael@0 1987 def isByteString(self):
michael@0 1988 return self.inner.isByteString()
michael@0 1989
michael@0 1990 def isDOMString(self):
michael@0 1991 return self.inner.isDOMString()
michael@0 1992
michael@0 1993 def isVoid(self):
michael@0 1994 return self.inner.isVoid()
michael@0 1995
michael@0 1996 def isSequence(self):
michael@0 1997 return self.inner.isSequence()
michael@0 1998
michael@0 1999 def isMozMap(self):
michael@0 2000 return self.inner.isMozMap()
michael@0 2001
michael@0 2002 def isArray(self):
michael@0 2003 return self.inner.isArray()
michael@0 2004
michael@0 2005 def isDictionary(self):
michael@0 2006 return self.inner.isDictionary()
michael@0 2007
michael@0 2008 def isArrayBuffer(self):
michael@0 2009 return self.inner.isArrayBuffer()
michael@0 2010
michael@0 2011 def isArrayBufferView(self):
michael@0 2012 return self.inner.isArrayBufferView()
michael@0 2013
michael@0 2014 def isTypedArray(self):
michael@0 2015 return self.inner.isTypedArray()
michael@0 2016
michael@0 2017 def isInterface(self):
michael@0 2018 return self.inner.isInterface()
michael@0 2019
michael@0 2020 def isCallbackInterface(self):
michael@0 2021 return self.inner.isCallbackInterface()
michael@0 2022
michael@0 2023 def isNonCallbackInterface(self):
michael@0 2024 return self.inner.isNonCallbackInterface()
michael@0 2025
michael@0 2026 def isComplete(self):
michael@0 2027 return False
michael@0 2028
michael@0 2029 def complete(self, parentScope):
michael@0 2030 if not self.inner.isComplete():
michael@0 2031 self.inner = self.inner.complete(parentScope)
michael@0 2032 assert self.inner.isComplete()
michael@0 2033 return self.inner
michael@0 2034
michael@0 2035 def finish(self, parentScope):
michael@0 2036 # Maybe the IDLObjectWithIdentifier for the typedef should be
michael@0 2037 # a separate thing from the type? If that happens, we can
michael@0 2038 # remove some hackery around avoiding isInterface() in
michael@0 2039 # Configuration.py.
michael@0 2040 self.complete(parentScope)
michael@0 2041
michael@0 2042 def validate(self):
michael@0 2043 pass
michael@0 2044
michael@0 2045 # Do we need a resolveType impl? I don't think it's particularly useful....
michael@0 2046
michael@0 2047 def tag(self):
michael@0 2048 return self.inner.tag()
michael@0 2049
michael@0 2050 def unroll(self):
michael@0 2051 return self.inner.unroll()
michael@0 2052
michael@0 2053 def isDistinguishableFrom(self, other):
michael@0 2054 return self.inner.isDistinguishableFrom(other)
michael@0 2055
michael@0 2056 def _getDependentObjects(self):
michael@0 2057 return self.inner._getDependentObjects()
michael@0 2058
michael@0 2059 class IDLWrapperType(IDLType):
michael@0 2060 def __init__(self, location, inner):
michael@0 2061 IDLType.__init__(self, location, inner.identifier.name)
michael@0 2062 self.inner = inner
michael@0 2063 self._identifier = inner.identifier
michael@0 2064 self.builtin = False
michael@0 2065
michael@0 2066 def __eq__(self, other):
michael@0 2067 return isinstance(other, IDLWrapperType) and \
michael@0 2068 self._identifier == other._identifier and \
michael@0 2069 self.builtin == other.builtin
michael@0 2070
michael@0 2071 def __str__(self):
michael@0 2072 return str(self.name) + " (Wrapper)"
michael@0 2073
michael@0 2074 def nullable(self):
michael@0 2075 return False
michael@0 2076
michael@0 2077 def isPrimitive(self):
michael@0 2078 return False
michael@0 2079
michael@0 2080 def isString(self):
michael@0 2081 return False
michael@0 2082
michael@0 2083 def isByteString(self):
michael@0 2084 return False
michael@0 2085
michael@0 2086 def isDOMString(self):
michael@0 2087 return False
michael@0 2088
michael@0 2089 def isVoid(self):
michael@0 2090 return False
michael@0 2091
michael@0 2092 def isSequence(self):
michael@0 2093 return False
michael@0 2094
michael@0 2095 def isArray(self):
michael@0 2096 return False
michael@0 2097
michael@0 2098 def isDictionary(self):
michael@0 2099 return isinstance(self.inner, IDLDictionary)
michael@0 2100
michael@0 2101 def isInterface(self):
michael@0 2102 return isinstance(self.inner, IDLInterface) or \
michael@0 2103 isinstance(self.inner, IDLExternalInterface)
michael@0 2104
michael@0 2105 def isCallbackInterface(self):
michael@0 2106 return self.isInterface() and self.inner.isCallback()
michael@0 2107
michael@0 2108 def isNonCallbackInterface(self):
michael@0 2109 return self.isInterface() and not self.inner.isCallback()
michael@0 2110
michael@0 2111 def isEnum(self):
michael@0 2112 return isinstance(self.inner, IDLEnum)
michael@0 2113
michael@0 2114 def isPromise(self):
michael@0 2115 return isinstance(self.inner, IDLInterface) and \
michael@0 2116 self.inner.identifier.name == "Promise"
michael@0 2117
michael@0 2118 def isSerializable(self):
michael@0 2119 if self.isInterface():
michael@0 2120 if self.inner.isExternal():
michael@0 2121 return False
michael@0 2122 return any(m.isMethod() and m.isJsonifier() for m in self.inner.members)
michael@0 2123 elif self.isEnum():
michael@0 2124 return True
michael@0 2125 elif self.isDictionary():
michael@0 2126 return all(m.type.isSerializable() for m in self.inner.members)
michael@0 2127 else:
michael@0 2128 raise WebIDLError("IDLWrapperType wraps type %s that we don't know if "
michael@0 2129 "is serializable" % type(self.inner), [self.location])
michael@0 2130
michael@0 2131 def resolveType(self, parentScope):
michael@0 2132 assert isinstance(parentScope, IDLScope)
michael@0 2133 self.inner.resolve(parentScope)
michael@0 2134
michael@0 2135 def isComplete(self):
michael@0 2136 return True
michael@0 2137
michael@0 2138 def tag(self):
michael@0 2139 if self.isInterface():
michael@0 2140 return IDLType.Tags.interface
michael@0 2141 elif self.isEnum():
michael@0 2142 return IDLType.Tags.enum
michael@0 2143 elif self.isDictionary():
michael@0 2144 return IDLType.Tags.dictionary
michael@0 2145 else:
michael@0 2146 assert False
michael@0 2147
michael@0 2148 def isDistinguishableFrom(self, other):
michael@0 2149 if other.isUnion():
michael@0 2150 # Just forward to the union; it'll deal
michael@0 2151 return other.isDistinguishableFrom(self)
michael@0 2152 assert self.isInterface() or self.isEnum() or self.isDictionary()
michael@0 2153 if self.isEnum():
michael@0 2154 return (other.isPrimitive() or other.isInterface() or other.isObject() or
michael@0 2155 other.isCallback() or other.isDictionary() or
michael@0 2156 other.isSequence() or other.isMozMap() or other.isArray() or
michael@0 2157 other.isDate())
michael@0 2158 if self.isDictionary() and other.nullable():
michael@0 2159 return False
michael@0 2160 if other.isPrimitive() or other.isString() or other.isEnum() or other.isDate():
michael@0 2161 return True
michael@0 2162 if self.isDictionary():
michael@0 2163 return other.isNonCallbackInterface()
michael@0 2164
michael@0 2165 assert self.isInterface()
michael@0 2166 if other.isInterface():
michael@0 2167 if other.isSpiderMonkeyInterface():
michael@0 2168 # Just let |other| handle things
michael@0 2169 return other.isDistinguishableFrom(self)
michael@0 2170 assert self.isGeckoInterface() and other.isGeckoInterface()
michael@0 2171 if self.inner.isExternal() or other.unroll().inner.isExternal():
michael@0 2172 return self != other
michael@0 2173 return (len(self.inner.interfacesBasedOnSelf &
michael@0 2174 other.unroll().inner.interfacesBasedOnSelf) == 0 and
michael@0 2175 (self.isNonCallbackInterface() or
michael@0 2176 other.isNonCallbackInterface()))
michael@0 2177 if (other.isDictionary() or other.isCallback() or
michael@0 2178 other.isSequence() or other.isMozMap() or other.isArray()):
michael@0 2179 return self.isNonCallbackInterface()
michael@0 2180
michael@0 2181 # Not much else |other| can be
michael@0 2182 assert other.isObject()
michael@0 2183 return False
michael@0 2184
michael@0 2185 def _getDependentObjects(self):
michael@0 2186 # NB: The codegen for an interface type depends on
michael@0 2187 # a) That the identifier is in fact an interface (as opposed to
michael@0 2188 # a dictionary or something else).
michael@0 2189 # b) The native type of the interface.
michael@0 2190 # If we depend on the interface object we will also depend on
michael@0 2191 # anything the interface depends on which is undesirable. We
michael@0 2192 # considered implementing a dependency just on the interface type
michael@0 2193 # file, but then every modification to an interface would cause this
michael@0 2194 # to be regenerated which is still undesirable. We decided not to
michael@0 2195 # depend on anything, reasoning that:
michael@0 2196 # 1) Changing the concrete type of the interface requires modifying
michael@0 2197 # Bindings.conf, which is still a global dependency.
michael@0 2198 # 2) Changing an interface to a dictionary (or vice versa) with the
michael@0 2199 # same identifier should be incredibly rare.
michael@0 2200 return set()
michael@0 2201
michael@0 2202 class IDLBuiltinType(IDLType):
michael@0 2203
michael@0 2204 Types = enum(
michael@0 2205 # The integer types
michael@0 2206 'byte',
michael@0 2207 'octet',
michael@0 2208 'short',
michael@0 2209 'unsigned_short',
michael@0 2210 'long',
michael@0 2211 'unsigned_long',
michael@0 2212 'long_long',
michael@0 2213 'unsigned_long_long',
michael@0 2214 # Additional primitive types
michael@0 2215 'boolean',
michael@0 2216 'unrestricted_float',
michael@0 2217 'float',
michael@0 2218 'unrestricted_double',
michael@0 2219 # IMPORTANT: "double" must be the last primitive type listed
michael@0 2220 'double',
michael@0 2221 # Other types
michael@0 2222 'any',
michael@0 2223 'domstring',
michael@0 2224 'bytestring',
michael@0 2225 'object',
michael@0 2226 'date',
michael@0 2227 'void',
michael@0 2228 # Funny stuff
michael@0 2229 'ArrayBuffer',
michael@0 2230 'ArrayBufferView',
michael@0 2231 'Int8Array',
michael@0 2232 'Uint8Array',
michael@0 2233 'Uint8ClampedArray',
michael@0 2234 'Int16Array',
michael@0 2235 'Uint16Array',
michael@0 2236 'Int32Array',
michael@0 2237 'Uint32Array',
michael@0 2238 'Float32Array',
michael@0 2239 'Float64Array'
michael@0 2240 )
michael@0 2241
michael@0 2242 TagLookup = {
michael@0 2243 Types.byte: IDLType.Tags.int8,
michael@0 2244 Types.octet: IDLType.Tags.uint8,
michael@0 2245 Types.short: IDLType.Tags.int16,
michael@0 2246 Types.unsigned_short: IDLType.Tags.uint16,
michael@0 2247 Types.long: IDLType.Tags.int32,
michael@0 2248 Types.unsigned_long: IDLType.Tags.uint32,
michael@0 2249 Types.long_long: IDLType.Tags.int64,
michael@0 2250 Types.unsigned_long_long: IDLType.Tags.uint64,
michael@0 2251 Types.boolean: IDLType.Tags.bool,
michael@0 2252 Types.unrestricted_float: IDLType.Tags.unrestricted_float,
michael@0 2253 Types.float: IDLType.Tags.float,
michael@0 2254 Types.unrestricted_double: IDLType.Tags.unrestricted_double,
michael@0 2255 Types.double: IDLType.Tags.double,
michael@0 2256 Types.any: IDLType.Tags.any,
michael@0 2257 Types.domstring: IDLType.Tags.domstring,
michael@0 2258 Types.bytestring: IDLType.Tags.bytestring,
michael@0 2259 Types.object: IDLType.Tags.object,
michael@0 2260 Types.date: IDLType.Tags.date,
michael@0 2261 Types.void: IDLType.Tags.void,
michael@0 2262 Types.ArrayBuffer: IDLType.Tags.interface,
michael@0 2263 Types.ArrayBufferView: IDLType.Tags.interface,
michael@0 2264 Types.Int8Array: IDLType.Tags.interface,
michael@0 2265 Types.Uint8Array: IDLType.Tags.interface,
michael@0 2266 Types.Uint8ClampedArray: IDLType.Tags.interface,
michael@0 2267 Types.Int16Array: IDLType.Tags.interface,
michael@0 2268 Types.Uint16Array: IDLType.Tags.interface,
michael@0 2269 Types.Int32Array: IDLType.Tags.interface,
michael@0 2270 Types.Uint32Array: IDLType.Tags.interface,
michael@0 2271 Types.Float32Array: IDLType.Tags.interface,
michael@0 2272 Types.Float64Array: IDLType.Tags.interface
michael@0 2273 }
michael@0 2274
michael@0 2275 def __init__(self, location, name, type):
michael@0 2276 IDLType.__init__(self, location, name)
michael@0 2277 self.builtin = True
michael@0 2278 self._typeTag = type
michael@0 2279
michael@0 2280 def isPrimitive(self):
michael@0 2281 return self._typeTag <= IDLBuiltinType.Types.double
michael@0 2282
michael@0 2283 def isBoolean(self):
michael@0 2284 return self._typeTag == IDLBuiltinType.Types.boolean
michael@0 2285
michael@0 2286 def isNumeric(self):
michael@0 2287 return self.isPrimitive() and not self.isBoolean()
michael@0 2288
michael@0 2289 def isString(self):
michael@0 2290 return self._typeTag == IDLBuiltinType.Types.domstring or \
michael@0 2291 self._typeTag == IDLBuiltinType.Types.bytestring
michael@0 2292
michael@0 2293 def isByteString(self):
michael@0 2294 return self._typeTag == IDLBuiltinType.Types.bytestring
michael@0 2295
michael@0 2296 def isDOMString(self):
michael@0 2297 return self._typeTag == IDLBuiltinType.Types.domstring
michael@0 2298
michael@0 2299 def isInteger(self):
michael@0 2300 return self._typeTag <= IDLBuiltinType.Types.unsigned_long_long
michael@0 2301
michael@0 2302 def isArrayBuffer(self):
michael@0 2303 return self._typeTag == IDLBuiltinType.Types.ArrayBuffer
michael@0 2304
michael@0 2305 def isArrayBufferView(self):
michael@0 2306 return self._typeTag == IDLBuiltinType.Types.ArrayBufferView
michael@0 2307
michael@0 2308 def isTypedArray(self):
michael@0 2309 return self._typeTag >= IDLBuiltinType.Types.Int8Array and \
michael@0 2310 self._typeTag <= IDLBuiltinType.Types.Float64Array
michael@0 2311
michael@0 2312 def isInterface(self):
michael@0 2313 # TypedArray things are interface types per the TypedArray spec,
michael@0 2314 # but we handle them as builtins because SpiderMonkey implements
michael@0 2315 # all of it internally.
michael@0 2316 return self.isArrayBuffer() or \
michael@0 2317 self.isArrayBufferView() or \
michael@0 2318 self.isTypedArray()
michael@0 2319
michael@0 2320 def isNonCallbackInterface(self):
michael@0 2321 # All the interfaces we can be are non-callback
michael@0 2322 return self.isInterface()
michael@0 2323
michael@0 2324 def isFloat(self):
michael@0 2325 return self._typeTag == IDLBuiltinType.Types.float or \
michael@0 2326 self._typeTag == IDLBuiltinType.Types.double or \
michael@0 2327 self._typeTag == IDLBuiltinType.Types.unrestricted_float or \
michael@0 2328 self._typeTag == IDLBuiltinType.Types.unrestricted_double
michael@0 2329
michael@0 2330 def isUnrestricted(self):
michael@0 2331 assert self.isFloat()
michael@0 2332 return self._typeTag == IDLBuiltinType.Types.unrestricted_float or \
michael@0 2333 self._typeTag == IDLBuiltinType.Types.unrestricted_double
michael@0 2334
michael@0 2335 def isSerializable(self):
michael@0 2336 return self.isPrimitive() or self.isDOMString() or self.isDate()
michael@0 2337
michael@0 2338 def includesRestrictedFloat(self):
michael@0 2339 return self.isFloat() and not self.isUnrestricted()
michael@0 2340
michael@0 2341 def tag(self):
michael@0 2342 return IDLBuiltinType.TagLookup[self._typeTag]
michael@0 2343
michael@0 2344 def isDistinguishableFrom(self, other):
michael@0 2345 if other.isUnion():
michael@0 2346 # Just forward to the union; it'll deal
michael@0 2347 return other.isDistinguishableFrom(self)
michael@0 2348 if self.isBoolean():
michael@0 2349 return (other.isNumeric() or other.isString() or other.isEnum() or
michael@0 2350 other.isInterface() or other.isObject() or
michael@0 2351 other.isCallback() or other.isDictionary() or
michael@0 2352 other.isSequence() or other.isMozMap() or other.isArray() or
michael@0 2353 other.isDate())
michael@0 2354 if self.isNumeric():
michael@0 2355 return (other.isBoolean() or other.isString() or other.isEnum() or
michael@0 2356 other.isInterface() or other.isObject() or
michael@0 2357 other.isCallback() or other.isDictionary() or
michael@0 2358 other.isSequence() or other.isMozMap() or other.isArray() or
michael@0 2359 other.isDate())
michael@0 2360 if self.isString():
michael@0 2361 return (other.isPrimitive() or other.isInterface() or
michael@0 2362 other.isObject() or
michael@0 2363 other.isCallback() or other.isDictionary() or
michael@0 2364 other.isSequence() or other.isMozMap() or other.isArray() or
michael@0 2365 other.isDate())
michael@0 2366 if self.isAny():
michael@0 2367 # Can't tell "any" apart from anything
michael@0 2368 return False
michael@0 2369 if self.isObject():
michael@0 2370 return other.isPrimitive() or other.isString() or other.isEnum()
michael@0 2371 if self.isDate():
michael@0 2372 return (other.isPrimitive() or other.isString() or other.isEnum() or
michael@0 2373 other.isInterface() or other.isCallback() or
michael@0 2374 other.isDictionary() or other.isSequence() or
michael@0 2375 other.isMozMap() or other.isArray())
michael@0 2376 if self.isVoid():
michael@0 2377 return not other.isVoid()
michael@0 2378 # Not much else we could be!
michael@0 2379 assert self.isSpiderMonkeyInterface()
michael@0 2380 # Like interfaces, but we know we're not a callback
michael@0 2381 return (other.isPrimitive() or other.isString() or other.isEnum() or
michael@0 2382 other.isCallback() or other.isDictionary() or
michael@0 2383 other.isSequence() or other.isMozMap() or other.isArray() or
michael@0 2384 other.isDate() or
michael@0 2385 (other.isInterface() and (
michael@0 2386 # ArrayBuffer is distinguishable from everything
michael@0 2387 # that's not an ArrayBuffer or a callback interface
michael@0 2388 (self.isArrayBuffer() and not other.isArrayBuffer()) or
michael@0 2389 # ArrayBufferView is distinguishable from everything
michael@0 2390 # that's not an ArrayBufferView or typed array.
michael@0 2391 (self.isArrayBufferView() and not other.isArrayBufferView() and
michael@0 2392 not other.isTypedArray()) or
michael@0 2393 # Typed arrays are distinguishable from everything
michael@0 2394 # except ArrayBufferView and the same type of typed
michael@0 2395 # array
michael@0 2396 (self.isTypedArray() and not other.isArrayBufferView() and not
michael@0 2397 (other.isTypedArray() and other.name == self.name)))))
michael@0 2398
michael@0 2399 def _getDependentObjects(self):
michael@0 2400 return set()
michael@0 2401
michael@0 2402 BuiltinTypes = {
michael@0 2403 IDLBuiltinType.Types.byte:
michael@0 2404 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Byte",
michael@0 2405 IDLBuiltinType.Types.byte),
michael@0 2406 IDLBuiltinType.Types.octet:
michael@0 2407 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Octet",
michael@0 2408 IDLBuiltinType.Types.octet),
michael@0 2409 IDLBuiltinType.Types.short:
michael@0 2410 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Short",
michael@0 2411 IDLBuiltinType.Types.short),
michael@0 2412 IDLBuiltinType.Types.unsigned_short:
michael@0 2413 IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedShort",
michael@0 2414 IDLBuiltinType.Types.unsigned_short),
michael@0 2415 IDLBuiltinType.Types.long:
michael@0 2416 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Long",
michael@0 2417 IDLBuiltinType.Types.long),
michael@0 2418 IDLBuiltinType.Types.unsigned_long:
michael@0 2419 IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedLong",
michael@0 2420 IDLBuiltinType.Types.unsigned_long),
michael@0 2421 IDLBuiltinType.Types.long_long:
michael@0 2422 IDLBuiltinType(BuiltinLocation("<builtin type>"), "LongLong",
michael@0 2423 IDLBuiltinType.Types.long_long),
michael@0 2424 IDLBuiltinType.Types.unsigned_long_long:
michael@0 2425 IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnsignedLongLong",
michael@0 2426 IDLBuiltinType.Types.unsigned_long_long),
michael@0 2427 IDLBuiltinType.Types.boolean:
michael@0 2428 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Boolean",
michael@0 2429 IDLBuiltinType.Types.boolean),
michael@0 2430 IDLBuiltinType.Types.float:
michael@0 2431 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float",
michael@0 2432 IDLBuiltinType.Types.float),
michael@0 2433 IDLBuiltinType.Types.unrestricted_float:
michael@0 2434 IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedFloat",
michael@0 2435 IDLBuiltinType.Types.unrestricted_float),
michael@0 2436 IDLBuiltinType.Types.double:
michael@0 2437 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Double",
michael@0 2438 IDLBuiltinType.Types.double),
michael@0 2439 IDLBuiltinType.Types.unrestricted_double:
michael@0 2440 IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedDouble",
michael@0 2441 IDLBuiltinType.Types.unrestricted_double),
michael@0 2442 IDLBuiltinType.Types.any:
michael@0 2443 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Any",
michael@0 2444 IDLBuiltinType.Types.any),
michael@0 2445 IDLBuiltinType.Types.domstring:
michael@0 2446 IDLBuiltinType(BuiltinLocation("<builtin type>"), "String",
michael@0 2447 IDLBuiltinType.Types.domstring),
michael@0 2448 IDLBuiltinType.Types.bytestring:
michael@0 2449 IDLBuiltinType(BuiltinLocation("<builtin type>"), "ByteString",
michael@0 2450 IDLBuiltinType.Types.bytestring),
michael@0 2451 IDLBuiltinType.Types.object:
michael@0 2452 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Object",
michael@0 2453 IDLBuiltinType.Types.object),
michael@0 2454 IDLBuiltinType.Types.date:
michael@0 2455 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Date",
michael@0 2456 IDLBuiltinType.Types.date),
michael@0 2457 IDLBuiltinType.Types.void:
michael@0 2458 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Void",
michael@0 2459 IDLBuiltinType.Types.void),
michael@0 2460 IDLBuiltinType.Types.ArrayBuffer:
michael@0 2461 IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBuffer",
michael@0 2462 IDLBuiltinType.Types.ArrayBuffer),
michael@0 2463 IDLBuiltinType.Types.ArrayBufferView:
michael@0 2464 IDLBuiltinType(BuiltinLocation("<builtin type>"), "ArrayBufferView",
michael@0 2465 IDLBuiltinType.Types.ArrayBufferView),
michael@0 2466 IDLBuiltinType.Types.Int8Array:
michael@0 2467 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int8Array",
michael@0 2468 IDLBuiltinType.Types.Int8Array),
michael@0 2469 IDLBuiltinType.Types.Uint8Array:
michael@0 2470 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint8Array",
michael@0 2471 IDLBuiltinType.Types.Uint8Array),
michael@0 2472 IDLBuiltinType.Types.Uint8ClampedArray:
michael@0 2473 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint8ClampedArray",
michael@0 2474 IDLBuiltinType.Types.Uint8ClampedArray),
michael@0 2475 IDLBuiltinType.Types.Int16Array:
michael@0 2476 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int16Array",
michael@0 2477 IDLBuiltinType.Types.Int16Array),
michael@0 2478 IDLBuiltinType.Types.Uint16Array:
michael@0 2479 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint16Array",
michael@0 2480 IDLBuiltinType.Types.Uint16Array),
michael@0 2481 IDLBuiltinType.Types.Int32Array:
michael@0 2482 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Int32Array",
michael@0 2483 IDLBuiltinType.Types.Int32Array),
michael@0 2484 IDLBuiltinType.Types.Uint32Array:
michael@0 2485 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Uint32Array",
michael@0 2486 IDLBuiltinType.Types.Uint32Array),
michael@0 2487 IDLBuiltinType.Types.Float32Array:
michael@0 2488 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float32Array",
michael@0 2489 IDLBuiltinType.Types.Float32Array),
michael@0 2490 IDLBuiltinType.Types.Float64Array:
michael@0 2491 IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float64Array",
michael@0 2492 IDLBuiltinType.Types.Float64Array)
michael@0 2493 }
michael@0 2494
michael@0 2495
michael@0 2496 integerTypeSizes = {
michael@0 2497 IDLBuiltinType.Types.byte: (-128, 127),
michael@0 2498 IDLBuiltinType.Types.octet: (0, 255),
michael@0 2499 IDLBuiltinType.Types.short: (-32768, 32767),
michael@0 2500 IDLBuiltinType.Types.unsigned_short: (0, 65535),
michael@0 2501 IDLBuiltinType.Types.long: (-2147483648, 2147483647),
michael@0 2502 IDLBuiltinType.Types.unsigned_long: (0, 4294967295),
michael@0 2503 IDLBuiltinType.Types.long_long: (-9223372036854775808,
michael@0 2504 9223372036854775807),
michael@0 2505 IDLBuiltinType.Types.unsigned_long_long: (0, 18446744073709551615)
michael@0 2506 }
michael@0 2507
michael@0 2508 def matchIntegerValueToType(value):
michael@0 2509 for type, extremes in integerTypeSizes.items():
michael@0 2510 (min, max) = extremes
michael@0 2511 if value <= max and value >= min:
michael@0 2512 return BuiltinTypes[type]
michael@0 2513
michael@0 2514 return None
michael@0 2515
michael@0 2516 class IDLValue(IDLObject):
michael@0 2517 def __init__(self, location, type, value):
michael@0 2518 IDLObject.__init__(self, location)
michael@0 2519 self.type = type
michael@0 2520 assert isinstance(type, IDLType)
michael@0 2521
michael@0 2522 self.value = value
michael@0 2523
michael@0 2524 def coerceToType(self, type, location):
michael@0 2525 if type == self.type:
michael@0 2526 return self # Nothing to do
michael@0 2527
michael@0 2528 # We first check for unions to ensure that even if the union is nullable
michael@0 2529 # we end up with the right flat member type, not the union's type.
michael@0 2530 if type.isUnion():
michael@0 2531 # We use the flat member types here, because if we have a nullable
michael@0 2532 # member type, or a nested union, we want the type the value
michael@0 2533 # actually coerces to, not the nullable or nested union type.
michael@0 2534 for subtype in type.unroll().flatMemberTypes:
michael@0 2535 try:
michael@0 2536 coercedValue = self.coerceToType(subtype, location)
michael@0 2537 # Create a new IDLValue to make sure that we have the
michael@0 2538 # correct float/double type. This is necessary because we
michael@0 2539 # use the value's type when it is a default value of a
michael@0 2540 # union, and the union cares about the exact float type.
michael@0 2541 return IDLValue(self.location, subtype, coercedValue.value)
michael@0 2542 except:
michael@0 2543 pass
michael@0 2544 # If the type allows null, rerun this matching on the inner type, except
michael@0 2545 # nullable enums. We handle those specially, because we want our
michael@0 2546 # default string values to stay strings even when assigned to a nullable
michael@0 2547 # enum.
michael@0 2548 elif type.nullable() and not type.isEnum():
michael@0 2549 innerValue = self.coerceToType(type.inner, location)
michael@0 2550 return IDLValue(self.location, type, innerValue.value)
michael@0 2551
michael@0 2552 elif self.type.isInteger() and type.isInteger():
michael@0 2553 # We're both integer types. See if we fit.
michael@0 2554
michael@0 2555 (min, max) = integerTypeSizes[type._typeTag]
michael@0 2556 if self.value <= max and self.value >= min:
michael@0 2557 # Promote
michael@0 2558 return IDLValue(self.location, type, self.value)
michael@0 2559 else:
michael@0 2560 raise WebIDLError("Value %s is out of range for type %s." %
michael@0 2561 (self.value, type), [location])
michael@0 2562 elif self.type.isInteger() and type.isFloat():
michael@0 2563 # Convert an integer literal into float
michael@0 2564 if -2**24 <= self.value <= 2**24:
michael@0 2565 floatType = BuiltinTypes[IDLBuiltinType.Types.float]
michael@0 2566 return IDLValue(self.location, floatType, float(self.value))
michael@0 2567 else:
michael@0 2568 raise WebIDLError("Converting value %s to %s will lose precision." %
michael@0 2569 (self.value, type), [location])
michael@0 2570 elif self.type.isString() and type.isEnum():
michael@0 2571 # Just keep our string, but make sure it's a valid value for this enum
michael@0 2572 enum = type.unroll().inner
michael@0 2573 if self.value not in enum.values():
michael@0 2574 raise WebIDLError("'%s' is not a valid default value for enum %s"
michael@0 2575 % (self.value, enum.identifier.name),
michael@0 2576 [location, enum.location])
michael@0 2577 return self
michael@0 2578 elif self.type.isFloat() and type.isFloat():
michael@0 2579 if (not type.isUnrestricted() and
michael@0 2580 (self.value == float("inf") or self.value == float("-inf") or
michael@0 2581 math.isnan(self.value))):
michael@0 2582 raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted"
michael@0 2583 % self.value, [location]);
michael@0 2584 return self
michael@0 2585 raise WebIDLError("Cannot coerce type %s to type %s." %
michael@0 2586 (self.type, type), [location])
michael@0 2587
michael@0 2588 def _getDependentObjects(self):
michael@0 2589 return set()
michael@0 2590
michael@0 2591 class IDLNullValue(IDLObject):
michael@0 2592 def __init__(self, location):
michael@0 2593 IDLObject.__init__(self, location)
michael@0 2594 self.type = None
michael@0 2595 self.value = None
michael@0 2596
michael@0 2597 def coerceToType(self, type, location):
michael@0 2598 if (not isinstance(type, IDLNullableType) and
michael@0 2599 not (type.isUnion() and type.hasNullableType) and
michael@0 2600 not (type.isUnion() and type.hasDictionaryType) and
michael@0 2601 not type.isDictionary() and
michael@0 2602 not type.isAny()):
michael@0 2603 raise WebIDLError("Cannot coerce null value to type %s." % type,
michael@0 2604 [location])
michael@0 2605
michael@0 2606 nullValue = IDLNullValue(self.location)
michael@0 2607 if type.isUnion() and not type.nullable() and type.hasDictionaryType:
michael@0 2608 # We're actually a default value for the union's dictionary member.
michael@0 2609 # Use its type.
michael@0 2610 for t in type.flatMemberTypes:
michael@0 2611 if t.isDictionary():
michael@0 2612 nullValue.type = t
michael@0 2613 return nullValue
michael@0 2614 nullValue.type = type
michael@0 2615 return nullValue
michael@0 2616
michael@0 2617 def _getDependentObjects(self):
michael@0 2618 return set()
michael@0 2619
michael@0 2620 class IDLUndefinedValue(IDLObject):
michael@0 2621 def __init__(self, location):
michael@0 2622 IDLObject.__init__(self, location)
michael@0 2623 self.type = None
michael@0 2624 self.value = None
michael@0 2625
michael@0 2626 def coerceToType(self, type, location):
michael@0 2627 if not type.isAny():
michael@0 2628 raise WebIDLError("Cannot coerce undefined value to type %s." % type,
michael@0 2629 [location])
michael@0 2630
michael@0 2631 undefinedValue = IDLUndefinedValue(self.location)
michael@0 2632 undefinedValue.type = type
michael@0 2633 return undefinedValue
michael@0 2634
michael@0 2635 def _getDependentObjects(self):
michael@0 2636 return set()
michael@0 2637
michael@0 2638 class IDLInterfaceMember(IDLObjectWithIdentifier):
michael@0 2639
michael@0 2640 Tags = enum(
michael@0 2641 'Const',
michael@0 2642 'Attr',
michael@0 2643 'Method'
michael@0 2644 )
michael@0 2645
michael@0 2646 Special = enum(
michael@0 2647 'Static',
michael@0 2648 'Stringifier'
michael@0 2649 )
michael@0 2650
michael@0 2651 def __init__(self, location, identifier, tag):
michael@0 2652 IDLObjectWithIdentifier.__init__(self, location, None, identifier)
michael@0 2653 self.tag = tag
michael@0 2654 self._extendedAttrDict = {}
michael@0 2655
michael@0 2656 def isMethod(self):
michael@0 2657 return self.tag == IDLInterfaceMember.Tags.Method
michael@0 2658
michael@0 2659 def isAttr(self):
michael@0 2660 return self.tag == IDLInterfaceMember.Tags.Attr
michael@0 2661
michael@0 2662 def isConst(self):
michael@0 2663 return self.tag == IDLInterfaceMember.Tags.Const
michael@0 2664
michael@0 2665 def addExtendedAttributes(self, attrs):
michael@0 2666 for attr in attrs:
michael@0 2667 self.handleExtendedAttribute(attr)
michael@0 2668 attrlist = attr.listValue()
michael@0 2669 self._extendedAttrDict[attr.identifier()] = attrlist if len(attrlist) else True
michael@0 2670
michael@0 2671 def handleExtendedAttribute(self, attr):
michael@0 2672 pass
michael@0 2673
michael@0 2674 def getExtendedAttribute(self, name):
michael@0 2675 return self._extendedAttrDict.get(name, None)
michael@0 2676
michael@0 2677 class IDLConst(IDLInterfaceMember):
michael@0 2678 def __init__(self, location, identifier, type, value):
michael@0 2679 IDLInterfaceMember.__init__(self, location, identifier,
michael@0 2680 IDLInterfaceMember.Tags.Const)
michael@0 2681
michael@0 2682 assert isinstance(type, IDLType)
michael@0 2683 if type.isDictionary():
michael@0 2684 raise WebIDLError("A constant cannot be of a dictionary type",
michael@0 2685 [self.location])
michael@0 2686 self.type = type
michael@0 2687 self.value = value
michael@0 2688
michael@0 2689 if identifier.name == "prototype":
michael@0 2690 raise WebIDLError("The identifier of a constant must not be 'prototype'",
michael@0 2691 [location])
michael@0 2692
michael@0 2693 def __str__(self):
michael@0 2694 return "'%s' const '%s'" % (self.type, self.identifier)
michael@0 2695
michael@0 2696 def finish(self, scope):
michael@0 2697 if not self.type.isComplete():
michael@0 2698 type = self.type.complete(scope)
michael@0 2699 if not type.isPrimitive() and not type.isString():
michael@0 2700 locations = [self.type.location, type.location]
michael@0 2701 try:
michael@0 2702 locations.append(type.inner.location)
michael@0 2703 except:
michael@0 2704 pass
michael@0 2705 raise WebIDLError("Incorrect type for constant", locations)
michael@0 2706 self.type = type
michael@0 2707
michael@0 2708 # The value might not match the type
michael@0 2709 coercedValue = self.value.coerceToType(self.type, self.location)
michael@0 2710 assert coercedValue
michael@0 2711
michael@0 2712 self.value = coercedValue
michael@0 2713
michael@0 2714 def validate(self):
michael@0 2715 pass
michael@0 2716
michael@0 2717 def _getDependentObjects(self):
michael@0 2718 return set([self.type, self.value])
michael@0 2719
michael@0 2720 class IDLAttribute(IDLInterfaceMember):
michael@0 2721 def __init__(self, location, identifier, type, readonly, inherit=False,
michael@0 2722 static=False, stringifier=False):
michael@0 2723 IDLInterfaceMember.__init__(self, location, identifier,
michael@0 2724 IDLInterfaceMember.Tags.Attr)
michael@0 2725
michael@0 2726 assert isinstance(type, IDLType)
michael@0 2727 self.type = type
michael@0 2728 self.readonly = readonly
michael@0 2729 self.inherit = inherit
michael@0 2730 self.static = static
michael@0 2731 self.lenientThis = False
michael@0 2732 self._unforgeable = False
michael@0 2733 self.stringifier = stringifier
michael@0 2734 self.enforceRange = False
michael@0 2735 self.clamp = False
michael@0 2736 self.slotIndex = None
michael@0 2737
michael@0 2738 if static and identifier.name == "prototype":
michael@0 2739 raise WebIDLError("The identifier of a static attribute must not be 'prototype'",
michael@0 2740 [location])
michael@0 2741
michael@0 2742 if readonly and inherit:
michael@0 2743 raise WebIDLError("An attribute cannot be both 'readonly' and 'inherit'",
michael@0 2744 [self.location])
michael@0 2745
michael@0 2746 def isStatic(self):
michael@0 2747 return self.static
michael@0 2748
michael@0 2749 def __str__(self):
michael@0 2750 return "'%s' attribute '%s'" % (self.type, self.identifier)
michael@0 2751
michael@0 2752 def finish(self, scope):
michael@0 2753 if not self.type.isComplete():
michael@0 2754 t = self.type.complete(scope)
michael@0 2755
michael@0 2756 assert not isinstance(t, IDLUnresolvedType)
michael@0 2757 assert not isinstance(t, IDLTypedefType)
michael@0 2758 assert not isinstance(t.name, IDLUnresolvedIdentifier)
michael@0 2759 self.type = t
michael@0 2760
michael@0 2761 if self.type.isDictionary() and not self.getExtendedAttribute("Cached"):
michael@0 2762 raise WebIDLError("An attribute cannot be of a dictionary type",
michael@0 2763 [self.location])
michael@0 2764 if self.type.isSequence() and not self.getExtendedAttribute("Cached"):
michael@0 2765 raise WebIDLError("A non-cached attribute cannot be of a sequence "
michael@0 2766 "type", [self.location])
michael@0 2767 if self.type.isMozMap() and not self.getExtendedAttribute("Cached"):
michael@0 2768 raise WebIDLError("A non-cached attribute cannot be of a MozMap "
michael@0 2769 "type", [self.location])
michael@0 2770 if self.type.isUnion():
michael@0 2771 for f in self.type.unroll().flatMemberTypes:
michael@0 2772 if f.isDictionary():
michael@0 2773 raise WebIDLError("An attribute cannot be of a union "
michael@0 2774 "type if one of its member types (or "
michael@0 2775 "one of its member types's member "
michael@0 2776 "types, and so on) is a dictionary "
michael@0 2777 "type", [self.location, f.location])
michael@0 2778 if f.isSequence():
michael@0 2779 raise WebIDLError("An attribute cannot be of a union "
michael@0 2780 "type if one of its member types (or "
michael@0 2781 "one of its member types's member "
michael@0 2782 "types, and so on) is a sequence "
michael@0 2783 "type", [self.location, f.location])
michael@0 2784 if f.isMozMap():
michael@0 2785 raise WebIDLError("An attribute cannot be of a union "
michael@0 2786 "type if one of its member types (or "
michael@0 2787 "one of its member types's member "
michael@0 2788 "types, and so on) is a MozMap "
michael@0 2789 "type", [self.location, f.location])
michael@0 2790 if not self.type.isInterface() and self.getExtendedAttribute("PutForwards"):
michael@0 2791 raise WebIDLError("An attribute with [PutForwards] must have an "
michael@0 2792 "interface type as its type", [self.location])
michael@0 2793
michael@0 2794 if not self.type.isInterface() and self.getExtendedAttribute("SameObject"):
michael@0 2795 raise WebIDLError("An attribute with [SameObject] must have an "
michael@0 2796 "interface type as its type", [self.location])
michael@0 2797
michael@0 2798 def validate(self):
michael@0 2799 if ((self.getExtendedAttribute("Cached") or
michael@0 2800 self.getExtendedAttribute("StoreInSlot")) and
michael@0 2801 not self.getExtendedAttribute("Constant") and
michael@0 2802 not self.getExtendedAttribute("Pure")):
michael@0 2803 raise WebIDLError("Cached attributes and attributes stored in "
michael@0 2804 "slots must be constant or pure, since the "
michael@0 2805 "getter won't always be called.",
michael@0 2806 [self.location])
michael@0 2807 if self.getExtendedAttribute("Frozen"):
michael@0 2808 if (not self.type.isSequence() and not self.type.isDictionary() and
michael@0 2809 not self.type.isMozMap()):
michael@0 2810 raise WebIDLError("[Frozen] is only allowed on "
michael@0 2811 "sequence-valued, dictionary-valued, and "
michael@0 2812 "MozMap-valued attributes",
michael@0 2813 [self.location])
michael@0 2814
michael@0 2815 def handleExtendedAttribute(self, attr):
michael@0 2816 identifier = attr.identifier()
michael@0 2817 if identifier == "SetterThrows" and self.readonly:
michael@0 2818 raise WebIDLError("Readonly attributes must not be flagged as "
michael@0 2819 "[SetterThrows]",
michael@0 2820 [self.location])
michael@0 2821 elif (((identifier == "Throws" or identifier == "GetterThrows") and
michael@0 2822 self.getExtendedAttribute("StoreInSlot")) or
michael@0 2823 (identifier == "StoreInSlot" and
michael@0 2824 (self.getExtendedAttribute("Throws") or
michael@0 2825 self.getExtendedAttribute("GetterThrows")))):
michael@0 2826 raise WebIDLError("Throwing things can't be [Pure] or [Constant] "
michael@0 2827 "or [SameObject] or [StoreInSlot]",
michael@0 2828 [attr.location])
michael@0 2829 elif identifier == "LenientThis":
michael@0 2830 if not attr.noArguments():
michael@0 2831 raise WebIDLError("[LenientThis] must take no arguments",
michael@0 2832 [attr.location])
michael@0 2833 if self.isStatic():
michael@0 2834 raise WebIDLError("[LenientThis] is only allowed on non-static "
michael@0 2835 "attributes", [attr.location, self.location])
michael@0 2836 if self.getExtendedAttribute("CrossOriginReadable"):
michael@0 2837 raise WebIDLError("[LenientThis] is not allowed in combination "
michael@0 2838 "with [CrossOriginReadable]",
michael@0 2839 [attr.location, self.location])
michael@0 2840 if self.getExtendedAttribute("CrossOriginWritable"):
michael@0 2841 raise WebIDLError("[LenientThis] is not allowed in combination "
michael@0 2842 "with [CrossOriginWritable]",
michael@0 2843 [attr.location, self.location])
michael@0 2844 self.lenientThis = True
michael@0 2845 elif identifier == "Unforgeable":
michael@0 2846 if not self.readonly:
michael@0 2847 raise WebIDLError("[Unforgeable] is only allowed on readonly "
michael@0 2848 "attributes", [attr.location, self.location])
michael@0 2849 if self.isStatic():
michael@0 2850 raise WebIDLError("[Unforgeable] is only allowed on non-static "
michael@0 2851 "attributes", [attr.location, self.location])
michael@0 2852 self._unforgeable = True
michael@0 2853 elif identifier == "SameObject" and not self.readonly:
michael@0 2854 raise WebIDLError("[SameObject] only allowed on readonly attributes",
michael@0 2855 [attr.location, self.location])
michael@0 2856 elif identifier == "Constant" and not self.readonly:
michael@0 2857 raise WebIDLError("[Constant] only allowed on readonly attributes",
michael@0 2858 [attr.location, self.location])
michael@0 2859 elif identifier == "PutForwards":
michael@0 2860 if not self.readonly:
michael@0 2861 raise WebIDLError("[PutForwards] is only allowed on readonly "
michael@0 2862 "attributes", [attr.location, self.location])
michael@0 2863 if self.isStatic():
michael@0 2864 raise WebIDLError("[PutForwards] is only allowed on non-static "
michael@0 2865 "attributes", [attr.location, self.location])
michael@0 2866 if self.getExtendedAttribute("Replaceable") is not None:
michael@0 2867 raise WebIDLError("[PutForwards] and [Replaceable] can't both "
michael@0 2868 "appear on the same attribute",
michael@0 2869 [attr.location, self.location])
michael@0 2870 if not attr.hasValue():
michael@0 2871 raise WebIDLError("[PutForwards] takes an identifier",
michael@0 2872 [attr.location, self.location])
michael@0 2873 elif identifier == "Replaceable":
michael@0 2874 if self.getExtendedAttribute("PutForwards") is not None:
michael@0 2875 raise WebIDLError("[PutForwards] and [Replaceable] can't both "
michael@0 2876 "appear on the same attribute",
michael@0 2877 [attr.location, self.location])
michael@0 2878 elif identifier == "LenientFloat":
michael@0 2879 if self.readonly:
michael@0 2880 raise WebIDLError("[LenientFloat] used on a readonly attribute",
michael@0 2881 [attr.location, self.location])
michael@0 2882 if not self.type.includesRestrictedFloat():
michael@0 2883 raise WebIDLError("[LenientFloat] used on an attribute with a "
michael@0 2884 "non-restricted-float type",
michael@0 2885 [attr.location, self.location])
michael@0 2886 elif identifier == "EnforceRange":
michael@0 2887 if self.readonly:
michael@0 2888 raise WebIDLError("[EnforceRange] used on a readonly attribute",
michael@0 2889 [attr.location, self.location])
michael@0 2890 self.enforceRange = True
michael@0 2891 elif identifier == "Clamp":
michael@0 2892 if self.readonly:
michael@0 2893 raise WebIDLError("[Clamp] used on a readonly attribute",
michael@0 2894 [attr.location, self.location])
michael@0 2895 self.clamp = True
michael@0 2896 elif identifier == "StoreInSlot":
michael@0 2897 if self.getExtendedAttribute("Cached"):
michael@0 2898 raise WebIDLError("[StoreInSlot] and [Cached] must not be "
michael@0 2899 "specified on the same attribute",
michael@0 2900 [attr.location, self.location])
michael@0 2901 elif identifier == "Cached":
michael@0 2902 if self.getExtendedAttribute("StoreInSlot"):
michael@0 2903 raise WebIDLError("[Cached] and [StoreInSlot] must not be "
michael@0 2904 "specified on the same attribute",
michael@0 2905 [attr.location, self.location])
michael@0 2906 elif (identifier == "CrossOriginReadable" or
michael@0 2907 identifier == "CrossOriginWritable"):
michael@0 2908 if not attr.noArguments():
michael@0 2909 raise WebIDLError("[%s] must take no arguments" % identifier,
michael@0 2910 [attr.location])
michael@0 2911 if self.isStatic():
michael@0 2912 raise WebIDLError("[%s] is only allowed on non-static "
michael@0 2913 "attributes" % identifier,
michael@0 2914 [attr.location, self.location])
michael@0 2915 if self.getExtendedAttribute("LenientThis"):
michael@0 2916 raise WebIDLError("[LenientThis] is not allowed in combination "
michael@0 2917 "with [%s]" % identifier,
michael@0 2918 [attr.location, self.location])
michael@0 2919 elif (identifier == "Pref" or
michael@0 2920 identifier == "SetterThrows" or
michael@0 2921 identifier == "Pure" or
michael@0 2922 identifier == "Throws" or
michael@0 2923 identifier == "GetterThrows" or
michael@0 2924 identifier == "ChromeOnly" or
michael@0 2925 identifier == "SameObject" or
michael@0 2926 identifier == "Constant" or
michael@0 2927 identifier == "Func" or
michael@0 2928 identifier == "Frozen" or
michael@0 2929 identifier == "AvailableIn" or
michael@0 2930 identifier == "NewObject"):
michael@0 2931 # Known attributes that we don't need to do anything with here
michael@0 2932 pass
michael@0 2933 else:
michael@0 2934 raise WebIDLError("Unknown extended attribute %s on attribute" % identifier,
michael@0 2935 [attr.location])
michael@0 2936 IDLInterfaceMember.handleExtendedAttribute(self, attr)
michael@0 2937
michael@0 2938 def resolve(self, parentScope):
michael@0 2939 assert isinstance(parentScope, IDLScope)
michael@0 2940 self.type.resolveType(parentScope)
michael@0 2941 IDLObjectWithIdentifier.resolve(self, parentScope)
michael@0 2942
michael@0 2943 def addExtendedAttributes(self, attrs):
michael@0 2944 attrs = self.checkForStringHandlingExtendedAttributes(attrs)
michael@0 2945 IDLInterfaceMember.addExtendedAttributes(self, attrs)
michael@0 2946
michael@0 2947 def hasLenientThis(self):
michael@0 2948 return self.lenientThis
michael@0 2949
michael@0 2950 def isUnforgeable(self):
michael@0 2951 return self._unforgeable
michael@0 2952
michael@0 2953 def _getDependentObjects(self):
michael@0 2954 return set([self.type])
michael@0 2955
michael@0 2956 class IDLArgument(IDLObjectWithIdentifier):
michael@0 2957 def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False):
michael@0 2958 IDLObjectWithIdentifier.__init__(self, location, None, identifier)
michael@0 2959
michael@0 2960 assert isinstance(type, IDLType)
michael@0 2961 self.type = type
michael@0 2962
michael@0 2963 self.optional = optional
michael@0 2964 self.defaultValue = defaultValue
michael@0 2965 self.variadic = variadic
michael@0 2966 self.dictionaryMember = dictionaryMember
michael@0 2967 self._isComplete = False
michael@0 2968 self.enforceRange = False
michael@0 2969 self.clamp = False
michael@0 2970 self._allowTreatNonCallableAsNull = False
michael@0 2971
michael@0 2972 assert not variadic or optional
michael@0 2973
michael@0 2974 def addExtendedAttributes(self, attrs):
michael@0 2975 attrs = self.checkForStringHandlingExtendedAttributes(
michael@0 2976 attrs,
michael@0 2977 isDictionaryMember=self.dictionaryMember,
michael@0 2978 isOptional=self.optional)
michael@0 2979 for attribute in attrs:
michael@0 2980 identifier = attribute.identifier()
michael@0 2981 if identifier == "Clamp":
michael@0 2982 if not attribute.noArguments():
michael@0 2983 raise WebIDLError("[Clamp] must take no arguments",
michael@0 2984 [attribute.location])
michael@0 2985 if self.enforceRange:
michael@0 2986 raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
michael@0 2987 [self.location]);
michael@0 2988 self.clamp = True
michael@0 2989 elif identifier == "EnforceRange":
michael@0 2990 if not attribute.noArguments():
michael@0 2991 raise WebIDLError("[EnforceRange] must take no arguments",
michael@0 2992 [attribute.location])
michael@0 2993 if self.clamp:
michael@0 2994 raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
michael@0 2995 [self.location]);
michael@0 2996 self.enforceRange = True
michael@0 2997 elif identifier == "TreatNonCallableAsNull":
michael@0 2998 self._allowTreatNonCallableAsNull = True
michael@0 2999 else:
michael@0 3000 raise WebIDLError("Unhandled extended attribute on an argument",
michael@0 3001 [attribute.location])
michael@0 3002
michael@0 3003 def isComplete(self):
michael@0 3004 return self._isComplete
michael@0 3005
michael@0 3006 def complete(self, scope):
michael@0 3007 if self._isComplete:
michael@0 3008 return
michael@0 3009
michael@0 3010 self._isComplete = True
michael@0 3011
michael@0 3012 if not self.type.isComplete():
michael@0 3013 type = self.type.complete(scope)
michael@0 3014 assert not isinstance(type, IDLUnresolvedType)
michael@0 3015 assert not isinstance(type, IDLTypedefType)
michael@0 3016 assert not isinstance(type.name, IDLUnresolvedIdentifier)
michael@0 3017 self.type = type
michael@0 3018
michael@0 3019 if ((self.type.isDictionary() or
michael@0 3020 self.type.isUnion() and self.type.unroll().hasDictionaryType) and
michael@0 3021 self.optional and not self.defaultValue):
michael@0 3022 # Default optional dictionaries to null, for simplicity,
michael@0 3023 # so the codegen doesn't have to special-case this.
michael@0 3024 self.defaultValue = IDLNullValue(self.location)
michael@0 3025 elif self.type.isAny():
michael@0 3026 assert (self.defaultValue is None or
michael@0 3027 isinstance(self.defaultValue, IDLNullValue))
michael@0 3028 # optional 'any' values always have a default value
michael@0 3029 if self.optional and not self.defaultValue and not self.variadic:
michael@0 3030 # Set the default value to undefined, for simplicity, so the
michael@0 3031 # codegen doesn't have to special-case this.
michael@0 3032 self.defaultValue = IDLUndefinedValue(self.location)
michael@0 3033
michael@0 3034 # Now do the coercing thing; this needs to happen after the
michael@0 3035 # above creation of a default value.
michael@0 3036 if self.defaultValue:
michael@0 3037 self.defaultValue = self.defaultValue.coerceToType(self.type,
michael@0 3038 self.location)
michael@0 3039 assert self.defaultValue
michael@0 3040
michael@0 3041 def allowTreatNonCallableAsNull(self):
michael@0 3042 return self._allowTreatNonCallableAsNull
michael@0 3043
michael@0 3044 def _getDependentObjects(self):
michael@0 3045 deps = set([self.type])
michael@0 3046 if self.defaultValue:
michael@0 3047 deps.add(self.defaultValue)
michael@0 3048 return deps
michael@0 3049
michael@0 3050 class IDLCallbackType(IDLType, IDLObjectWithScope):
michael@0 3051 def __init__(self, location, parentScope, identifier, returnType, arguments):
michael@0 3052 assert isinstance(returnType, IDLType)
michael@0 3053
michael@0 3054 IDLType.__init__(self, location, identifier.name)
michael@0 3055
michael@0 3056 self._returnType = returnType
michael@0 3057 # Clone the list
michael@0 3058 self._arguments = list(arguments)
michael@0 3059
michael@0 3060 IDLObjectWithScope.__init__(self, location, parentScope, identifier)
michael@0 3061
michael@0 3062 for (returnType, arguments) in self.signatures():
michael@0 3063 for argument in arguments:
michael@0 3064 argument.resolve(self)
michael@0 3065
michael@0 3066 self._treatNonCallableAsNull = False
michael@0 3067 self._treatNonObjectAsNull = False
michael@0 3068
michael@0 3069 def isCallback(self):
michael@0 3070 return True
michael@0 3071
michael@0 3072 def signatures(self):
michael@0 3073 return [(self._returnType, self._arguments)]
michael@0 3074
michael@0 3075 def tag(self):
michael@0 3076 return IDLType.Tags.callback
michael@0 3077
michael@0 3078 def finish(self, scope):
michael@0 3079 if not self._returnType.isComplete():
michael@0 3080 type = self._returnType.complete(scope)
michael@0 3081
michael@0 3082 assert not isinstance(type, IDLUnresolvedType)
michael@0 3083 assert not isinstance(type, IDLTypedefType)
michael@0 3084 assert not isinstance(type.name, IDLUnresolvedIdentifier)
michael@0 3085 self._returnType = type
michael@0 3086
michael@0 3087 for argument in self._arguments:
michael@0 3088 if argument.type.isComplete():
michael@0 3089 continue
michael@0 3090
michael@0 3091 type = argument.type.complete(scope)
michael@0 3092
michael@0 3093 assert not isinstance(type, IDLUnresolvedType)
michael@0 3094 assert not isinstance(type, IDLTypedefType)
michael@0 3095 assert not isinstance(type.name, IDLUnresolvedIdentifier)
michael@0 3096 argument.type = type
michael@0 3097
michael@0 3098 def validate(self):
michael@0 3099 pass
michael@0 3100
michael@0 3101 def isDistinguishableFrom(self, other):
michael@0 3102 if other.isUnion():
michael@0 3103 # Just forward to the union; it'll deal
michael@0 3104 return other.isDistinguishableFrom(self)
michael@0 3105 return (other.isPrimitive() or other.isString() or other.isEnum() or
michael@0 3106 other.isNonCallbackInterface() or other.isDate())
michael@0 3107
michael@0 3108 def addExtendedAttributes(self, attrs):
michael@0 3109 unhandledAttrs = []
michael@0 3110 for attr in attrs:
michael@0 3111 if attr.identifier() == "TreatNonCallableAsNull":
michael@0 3112 self._treatNonCallableAsNull = True
michael@0 3113 elif attr.identifier() == "TreatNonObjectAsNull":
michael@0 3114 self._treatNonObjectAsNull = True
michael@0 3115 else:
michael@0 3116 unhandledAttrs.append(attr)
michael@0 3117 if self._treatNonCallableAsNull and self._treatNonObjectAsNull:
michael@0 3118 raise WebIDLError("Cannot specify both [TreatNonCallableAsNull] "
michael@0 3119 "and [TreatNonObjectAsNull]", [self.location])
michael@0 3120 if len(unhandledAttrs) != 0:
michael@0 3121 IDLType.addExtendedAttributes(self, unhandledAttrs)
michael@0 3122
michael@0 3123 def _getDependentObjects(self):
michael@0 3124 return set([self._returnType] + self._arguments)
michael@0 3125
michael@0 3126 class IDLMethodOverload:
michael@0 3127 """
michael@0 3128 A class that represents a single overload of a WebIDL method. This is not
michael@0 3129 quite the same as an element of the "effective overload set" in the spec,
michael@0 3130 because separate IDLMethodOverloads are not created based on arguments being
michael@0 3131 optional. Rather, when multiple methods have the same name, there is an
michael@0 3132 IDLMethodOverload for each one, all hanging off an IDLMethod representing
michael@0 3133 the full set of overloads.
michael@0 3134 """
michael@0 3135 def __init__(self, returnType, arguments, location):
michael@0 3136 self.returnType = returnType
michael@0 3137 # Clone the list of arguments, just in case
michael@0 3138 self.arguments = list(arguments)
michael@0 3139 self.location = location
michael@0 3140
michael@0 3141 def _getDependentObjects(self):
michael@0 3142 deps = set(self.arguments)
michael@0 3143 deps.add(self.returnType)
michael@0 3144 return deps
michael@0 3145
michael@0 3146 class IDLMethod(IDLInterfaceMember, IDLScope):
michael@0 3147
michael@0 3148 Special = enum(
michael@0 3149 'Getter',
michael@0 3150 'Setter',
michael@0 3151 'Creator',
michael@0 3152 'Deleter',
michael@0 3153 'LegacyCaller',
michael@0 3154 base=IDLInterfaceMember.Special
michael@0 3155 )
michael@0 3156
michael@0 3157 TypeSuffixModifier = enum(
michael@0 3158 'None',
michael@0 3159 'QMark',
michael@0 3160 'Brackets'
michael@0 3161 )
michael@0 3162
michael@0 3163 NamedOrIndexed = enum(
michael@0 3164 'Neither',
michael@0 3165 'Named',
michael@0 3166 'Indexed'
michael@0 3167 )
michael@0 3168
michael@0 3169 def __init__(self, location, identifier, returnType, arguments,
michael@0 3170 static=False, getter=False, setter=False, creator=False,
michael@0 3171 deleter=False, specialType=NamedOrIndexed.Neither,
michael@0 3172 legacycaller=False, stringifier=False, jsonifier=False):
michael@0 3173 # REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
michael@0 3174 IDLInterfaceMember.__init__(self, location, identifier,
michael@0 3175 IDLInterfaceMember.Tags.Method)
michael@0 3176
michael@0 3177 self._hasOverloads = False
michael@0 3178
michael@0 3179 assert isinstance(returnType, IDLType)
michael@0 3180
michael@0 3181 # self._overloads is a list of IDLMethodOverloads
michael@0 3182 self._overloads = [IDLMethodOverload(returnType, arguments, location)]
michael@0 3183
michael@0 3184 assert isinstance(static, bool)
michael@0 3185 self._static = static
michael@0 3186 assert isinstance(getter, bool)
michael@0 3187 self._getter = getter
michael@0 3188 assert isinstance(setter, bool)
michael@0 3189 self._setter = setter
michael@0 3190 assert isinstance(creator, bool)
michael@0 3191 self._creator = creator
michael@0 3192 assert isinstance(deleter, bool)
michael@0 3193 self._deleter = deleter
michael@0 3194 assert isinstance(legacycaller, bool)
michael@0 3195 self._legacycaller = legacycaller
michael@0 3196 assert isinstance(stringifier, bool)
michael@0 3197 self._stringifier = stringifier
michael@0 3198 assert isinstance(jsonifier, bool)
michael@0 3199 self._jsonifier = jsonifier
michael@0 3200 self._specialType = specialType
michael@0 3201
michael@0 3202 if static and identifier.name == "prototype":
michael@0 3203 raise WebIDLError("The identifier of a static operation must not be 'prototype'",
michael@0 3204 [location])
michael@0 3205
michael@0 3206 self.assertSignatureConstraints()
michael@0 3207
michael@0 3208 def __str__(self):
michael@0 3209 return "Method '%s'" % self.identifier
michael@0 3210
michael@0 3211 def assertSignatureConstraints(self):
michael@0 3212 if self._getter or self._deleter:
michael@0 3213 assert len(self._overloads) == 1
michael@0 3214 overload = self._overloads[0]
michael@0 3215 arguments = overload.arguments
michael@0 3216 assert len(arguments) == 1
michael@0 3217 assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \
michael@0 3218 arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]
michael@0 3219 assert not arguments[0].optional and not arguments[0].variadic
michael@0 3220 assert not self._getter or not overload.returnType.isVoid()
michael@0 3221
michael@0 3222 if self._setter or self._creator:
michael@0 3223 assert len(self._overloads) == 1
michael@0 3224 arguments = self._overloads[0].arguments
michael@0 3225 assert len(arguments) == 2
michael@0 3226 assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \
michael@0 3227 arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]
michael@0 3228 assert not arguments[0].optional and not arguments[0].variadic
michael@0 3229 assert not arguments[1].optional and not arguments[1].variadic
michael@0 3230
michael@0 3231 if self._stringifier:
michael@0 3232 assert len(self._overloads) == 1
michael@0 3233 overload = self._overloads[0]
michael@0 3234 assert len(overload.arguments) == 0
michael@0 3235 assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring]
michael@0 3236
michael@0 3237 if self._jsonifier:
michael@0 3238 assert len(self._overloads) == 1
michael@0 3239 overload = self._overloads[0]
michael@0 3240 assert len(overload.arguments) == 0
michael@0 3241 assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.object]
michael@0 3242
michael@0 3243 def isStatic(self):
michael@0 3244 return self._static
michael@0 3245
michael@0 3246 def isGetter(self):
michael@0 3247 return self._getter
michael@0 3248
michael@0 3249 def isSetter(self):
michael@0 3250 return self._setter
michael@0 3251
michael@0 3252 def isCreator(self):
michael@0 3253 return self._creator
michael@0 3254
michael@0 3255 def isDeleter(self):
michael@0 3256 return self._deleter
michael@0 3257
michael@0 3258 def isNamed(self):
michael@0 3259 assert self._specialType == IDLMethod.NamedOrIndexed.Named or \
michael@0 3260 self._specialType == IDLMethod.NamedOrIndexed.Indexed
michael@0 3261 return self._specialType == IDLMethod.NamedOrIndexed.Named
michael@0 3262
michael@0 3263 def isIndexed(self):
michael@0 3264 assert self._specialType == IDLMethod.NamedOrIndexed.Named or \
michael@0 3265 self._specialType == IDLMethod.NamedOrIndexed.Indexed
michael@0 3266 return self._specialType == IDLMethod.NamedOrIndexed.Indexed
michael@0 3267
michael@0 3268 def isLegacycaller(self):
michael@0 3269 return self._legacycaller
michael@0 3270
michael@0 3271 def isStringifier(self):
michael@0 3272 return self._stringifier
michael@0 3273
michael@0 3274 def isJsonifier(self):
michael@0 3275 return self._jsonifier
michael@0 3276
michael@0 3277 def hasOverloads(self):
michael@0 3278 return self._hasOverloads
michael@0 3279
michael@0 3280 def isIdentifierLess(self):
michael@0 3281 return self.identifier.name[:2] == "__" and self.identifier.name != "__noSuchMethod__"
michael@0 3282
michael@0 3283 def resolve(self, parentScope):
michael@0 3284 assert isinstance(parentScope, IDLScope)
michael@0 3285 IDLObjectWithIdentifier.resolve(self, parentScope)
michael@0 3286 IDLScope.__init__(self, self.location, parentScope, self.identifier)
michael@0 3287 for (returnType, arguments) in self.signatures():
michael@0 3288 for argument in arguments:
michael@0 3289 argument.resolve(self)
michael@0 3290
michael@0 3291 def addOverload(self, method):
michael@0 3292 assert len(method._overloads) == 1
michael@0 3293
michael@0 3294 if self._extendedAttrDict != method ._extendedAttrDict:
michael@0 3295 raise WebIDLError("Extended attributes differ on different "
michael@0 3296 "overloads of %s" % method.identifier,
michael@0 3297 [self.location, method.location])
michael@0 3298
michael@0 3299 self._overloads.extend(method._overloads)
michael@0 3300
michael@0 3301 self._hasOverloads = True
michael@0 3302
michael@0 3303 if self.isStatic() != method.isStatic():
michael@0 3304 raise WebIDLError("Overloaded identifier %s appears with different values of the 'static' attribute" % method.identifier,
michael@0 3305 [method.location])
michael@0 3306
michael@0 3307 if self.isLegacycaller() != method.isLegacycaller():
michael@0 3308 raise WebIDLError("Overloaded identifier %s appears with different values of the 'legacycaller' attribute" % method.identifier,
michael@0 3309 [method.location])
michael@0 3310
michael@0 3311 # Can't overload special things!
michael@0 3312 assert not self.isGetter()
michael@0 3313 assert not method.isGetter()
michael@0 3314 assert not self.isSetter()
michael@0 3315 assert not method.isSetter()
michael@0 3316 assert not self.isCreator()
michael@0 3317 assert not method.isCreator()
michael@0 3318 assert not self.isDeleter()
michael@0 3319 assert not method.isDeleter()
michael@0 3320 assert not self.isStringifier()
michael@0 3321 assert not method.isStringifier()
michael@0 3322 assert not self.isJsonifier()
michael@0 3323 assert not method.isJsonifier()
michael@0 3324
michael@0 3325 return self
michael@0 3326
michael@0 3327 def signatures(self):
michael@0 3328 return [(overload.returnType, overload.arguments) for overload in
michael@0 3329 self._overloads]
michael@0 3330
michael@0 3331 def finish(self, scope):
michael@0 3332 overloadWithPromiseReturnType = None
michael@0 3333 overloadWithoutPromiseReturnType = None
michael@0 3334 for overload in self._overloads:
michael@0 3335 variadicArgument = None
michael@0 3336
michael@0 3337 arguments = overload.arguments
michael@0 3338 for (idx, argument) in enumerate(arguments):
michael@0 3339 if not argument.isComplete():
michael@0 3340 argument.complete(scope)
michael@0 3341 assert argument.type.isComplete()
michael@0 3342
michael@0 3343 if (argument.type.isDictionary() or
michael@0 3344 (argument.type.isUnion() and
michael@0 3345 argument.type.unroll().hasDictionaryType)):
michael@0 3346 # Dictionaries and unions containing dictionaries at the
michael@0 3347 # end of the list or followed by optional arguments must be
michael@0 3348 # optional.
michael@0 3349 if (not argument.optional and
michael@0 3350 all(arg.optional for arg in arguments[idx+1:])):
michael@0 3351 raise WebIDLError("Dictionary argument or union "
michael@0 3352 "argument containing a dictionary "
michael@0 3353 "not followed by a required argument "
michael@0 3354 "must be optional",
michael@0 3355 [argument.location])
michael@0 3356
michael@0 3357 # An argument cannot be a Nullable Dictionary
michael@0 3358 if argument.type.nullable():
michael@0 3359 raise WebIDLError("An argument cannot be a nullable "
michael@0 3360 "dictionary or nullable union "
michael@0 3361 "containing a dictionary",
michael@0 3362 [argument.location])
michael@0 3363
michael@0 3364 # Only the last argument can be variadic
michael@0 3365 if variadicArgument:
michael@0 3366 raise WebIDLError("Variadic argument is not last argument",
michael@0 3367 [variadicArgument.location])
michael@0 3368 if argument.variadic:
michael@0 3369 variadicArgument = argument
michael@0 3370
michael@0 3371 returnType = overload.returnType
michael@0 3372 if not returnType.isComplete():
michael@0 3373 returnType = returnType.complete(scope)
michael@0 3374 assert not isinstance(returnType, IDLUnresolvedType)
michael@0 3375 assert not isinstance(returnType, IDLTypedefType)
michael@0 3376 assert not isinstance(returnType.name, IDLUnresolvedIdentifier)
michael@0 3377 overload.returnType = returnType
michael@0 3378
michael@0 3379 if returnType.isPromise():
michael@0 3380 overloadWithPromiseReturnType = overload
michael@0 3381 else:
michael@0 3382 overloadWithoutPromiseReturnType = overload
michael@0 3383
michael@0 3384 # Make sure either all our overloads return Promises or none do
michael@0 3385 if overloadWithPromiseReturnType and overloadWithoutPromiseReturnType:
michael@0 3386 raise WebIDLError("We have overloads with both Promise and "
michael@0 3387 "non-Promise return types",
michael@0 3388 [overloadWithPromiseReturnType.location,
michael@0 3389 overloadWithoutPromiseReturnType.location])
michael@0 3390
michael@0 3391 if overloadWithPromiseReturnType and self._legacycaller:
michael@0 3392 raise WebIDLError("May not have a Promise return type for a "
michael@0 3393 "legacycaller.",
michael@0 3394 [overloadWithPromiseReturnType.location])
michael@0 3395
michael@0 3396 # Now compute various information that will be used by the
michael@0 3397 # WebIDL overload resolution algorithm.
michael@0 3398 self.maxArgCount = max(len(s[1]) for s in self.signatures())
michael@0 3399 self.allowedArgCounts = [ i for i in range(self.maxArgCount+1)
michael@0 3400 if len(self.signaturesForArgCount(i)) != 0 ]
michael@0 3401
michael@0 3402 def validate(self):
michael@0 3403 # Make sure our overloads are properly distinguishable and don't have
michael@0 3404 # different argument types before the distinguishing args.
michael@0 3405 for argCount in self.allowedArgCounts:
michael@0 3406 possibleOverloads = self.overloadsForArgCount(argCount)
michael@0 3407 if len(possibleOverloads) == 1:
michael@0 3408 continue
michael@0 3409 distinguishingIndex = self.distinguishingIndexForArgCount(argCount)
michael@0 3410 for idx in range(distinguishingIndex):
michael@0 3411 firstSigType = possibleOverloads[0].arguments[idx].type
michael@0 3412 for overload in possibleOverloads[1:]:
michael@0 3413 if overload.arguments[idx].type != firstSigType:
michael@0 3414 raise WebIDLError(
michael@0 3415 "Signatures for method '%s' with %d arguments have "
michael@0 3416 "different types of arguments at index %d, which "
michael@0 3417 "is before distinguishing index %d" %
michael@0 3418 (self.identifier.name, argCount, idx,
michael@0 3419 distinguishingIndex),
michael@0 3420 [self.location, overload.location])
michael@0 3421
michael@0 3422 def overloadsForArgCount(self, argc):
michael@0 3423 return [overload for overload in self._overloads if
michael@0 3424 len(overload.arguments) == argc or
michael@0 3425 (len(overload.arguments) > argc and
michael@0 3426 all(arg.optional for arg in overload.arguments[argc:])) or
michael@0 3427 (len(overload.arguments) < argc and
michael@0 3428 len(overload.arguments) > 0 and
michael@0 3429 overload.arguments[-1].variadic)]
michael@0 3430
michael@0 3431 def signaturesForArgCount(self, argc):
michael@0 3432 return [(overload.returnType, overload.arguments) for overload
michael@0 3433 in self.overloadsForArgCount(argc)]
michael@0 3434
michael@0 3435 def locationsForArgCount(self, argc):
michael@0 3436 return [overload.location for overload in self.overloadsForArgCount(argc)]
michael@0 3437
michael@0 3438 def distinguishingIndexForArgCount(self, argc):
michael@0 3439 def isValidDistinguishingIndex(idx, signatures):
michael@0 3440 for (firstSigIndex, (firstRetval, firstArgs)) in enumerate(signatures[:-1]):
michael@0 3441 for (secondRetval, secondArgs) in signatures[firstSigIndex+1:]:
michael@0 3442 if idx < len(firstArgs):
michael@0 3443 firstType = firstArgs[idx].type
michael@0 3444 else:
michael@0 3445 assert(firstArgs[-1].variadic)
michael@0 3446 firstType = firstArgs[-1].type
michael@0 3447 if idx < len(secondArgs):
michael@0 3448 secondType = secondArgs[idx].type
michael@0 3449 else:
michael@0 3450 assert(secondArgs[-1].variadic)
michael@0 3451 secondType = secondArgs[-1].type
michael@0 3452 if not firstType.isDistinguishableFrom(secondType):
michael@0 3453 return False
michael@0 3454 return True
michael@0 3455 signatures = self.signaturesForArgCount(argc)
michael@0 3456 for idx in range(argc):
michael@0 3457 if isValidDistinguishingIndex(idx, signatures):
michael@0 3458 return idx
michael@0 3459 # No valid distinguishing index. Time to throw
michael@0 3460 locations = self.locationsForArgCount(argc)
michael@0 3461 raise WebIDLError("Signatures with %d arguments for method '%s' are not "
michael@0 3462 "distinguishable" % (argc, self.identifier.name),
michael@0 3463 locations)
michael@0 3464
michael@0 3465 def handleExtendedAttribute(self, attr):
michael@0 3466 identifier = attr.identifier()
michael@0 3467 if identifier == "GetterThrows":
michael@0 3468 raise WebIDLError("Methods must not be flagged as "
michael@0 3469 "[GetterThrows]",
michael@0 3470 [attr.location, self.location])
michael@0 3471 elif identifier == "SetterThrows":
michael@0 3472 raise WebIDLError("Methods must not be flagged as "
michael@0 3473 "[SetterThrows]",
michael@0 3474 [attr.location, self.location])
michael@0 3475 elif identifier == "Unforgeable":
michael@0 3476 raise WebIDLError("Methods must not be flagged as "
michael@0 3477 "[Unforgeable]",
michael@0 3478 [attr.location, self.location])
michael@0 3479 elif identifier == "SameObject":
michael@0 3480 raise WebIDLError("Methods must not be flagged as [SameObject]",
michael@0 3481 [attr.location, self.location]);
michael@0 3482 elif identifier == "Constant":
michael@0 3483 raise WebIDLError("Methods must not be flagged as [Constant]",
michael@0 3484 [attr.location, self.location]);
michael@0 3485 elif identifier == "PutForwards":
michael@0 3486 raise WebIDLError("Only attributes support [PutForwards]",
michael@0 3487 [attr.location, self.location])
michael@0 3488 elif identifier == "LenientFloat":
michael@0 3489 # This is called before we've done overload resolution
michael@0 3490 assert len(self.signatures()) == 1
michael@0 3491 sig = self.signatures()[0]
michael@0 3492 if not sig[0].isVoid():
michael@0 3493 raise WebIDLError("[LenientFloat] used on a non-void method",
michael@0 3494 [attr.location, self.location])
michael@0 3495 if not any(arg.type.includesRestrictedFloat() for arg in sig[1]):
michael@0 3496 raise WebIDLError("[LenientFloat] used on an operation with no "
michael@0 3497 "restricted float type arguments",
michael@0 3498 [attr.location, self.location])
michael@0 3499 elif (identifier == "Throws" or
michael@0 3500 identifier == "NewObject" or
michael@0 3501 identifier == "ChromeOnly" or
michael@0 3502 identifier == "Pref" or
michael@0 3503 identifier == "Func" or
michael@0 3504 identifier == "AvailableIn" or
michael@0 3505 identifier == "Pure" or
michael@0 3506 identifier == "CrossOriginCallable" or
michael@0 3507 identifier == "WebGLHandlesContextLoss"):
michael@0 3508 # Known attributes that we don't need to do anything with here
michael@0 3509 pass
michael@0 3510 else:
michael@0 3511 raise WebIDLError("Unknown extended attribute %s on method" % identifier,
michael@0 3512 [attr.location])
michael@0 3513 IDLInterfaceMember.handleExtendedAttribute(self, attr)
michael@0 3514
michael@0 3515 def returnsPromise(self):
michael@0 3516 return self._overloads[0].returnType.isPromise()
michael@0 3517
michael@0 3518 def _getDependentObjects(self):
michael@0 3519 deps = set()
michael@0 3520 for overload in self._overloads:
michael@0 3521 deps.union(overload._getDependentObjects())
michael@0 3522 return deps
michael@0 3523
michael@0 3524 class IDLImplementsStatement(IDLObject):
michael@0 3525 def __init__(self, location, implementor, implementee):
michael@0 3526 IDLObject.__init__(self, location)
michael@0 3527 self.implementor = implementor;
michael@0 3528 self.implementee = implementee
michael@0 3529
michael@0 3530 def finish(self, scope):
michael@0 3531 assert(isinstance(self.implementor, IDLIdentifierPlaceholder))
michael@0 3532 assert(isinstance(self.implementee, IDLIdentifierPlaceholder))
michael@0 3533 implementor = self.implementor.finish(scope)
michael@0 3534 implementee = self.implementee.finish(scope)
michael@0 3535 # NOTE: we depend on not setting self.implementor and
michael@0 3536 # self.implementee here to keep track of the original
michael@0 3537 # locations.
michael@0 3538 if not isinstance(implementor, IDLInterface):
michael@0 3539 raise WebIDLError("Left-hand side of 'implements' is not an "
michael@0 3540 "interface",
michael@0 3541 [self.implementor.location])
michael@0 3542 if implementor.isCallback():
michael@0 3543 raise WebIDLError("Left-hand side of 'implements' is a callback "
michael@0 3544 "interface",
michael@0 3545 [self.implementor.location])
michael@0 3546 if not isinstance(implementee, IDLInterface):
michael@0 3547 raise WebIDLError("Right-hand side of 'implements' is not an "
michael@0 3548 "interface",
michael@0 3549 [self.implementee.location])
michael@0 3550 if implementee.isCallback():
michael@0 3551 raise WebIDLError("Right-hand side of 'implements' is a callback "
michael@0 3552 "interface",
michael@0 3553 [self.implementee.location])
michael@0 3554 implementor.addImplementedInterface(implementee)
michael@0 3555
michael@0 3556 def validate(self):
michael@0 3557 pass
michael@0 3558
michael@0 3559 def addExtendedAttributes(self, attrs):
michael@0 3560 assert len(attrs) == 0
michael@0 3561
michael@0 3562 class IDLExtendedAttribute(IDLObject):
michael@0 3563 """
michael@0 3564 A class to represent IDL extended attributes so we can give them locations
michael@0 3565 """
michael@0 3566 def __init__(self, location, tuple):
michael@0 3567 IDLObject.__init__(self, location)
michael@0 3568 self._tuple = tuple
michael@0 3569
michael@0 3570 def identifier(self):
michael@0 3571 return self._tuple[0]
michael@0 3572
michael@0 3573 def noArguments(self):
michael@0 3574 return len(self._tuple) == 1
michael@0 3575
michael@0 3576 def hasValue(self):
michael@0 3577 return len(self._tuple) >= 2 and isinstance(self._tuple[1], str)
michael@0 3578
michael@0 3579 def value(self):
michael@0 3580 assert(self.hasValue())
michael@0 3581 return self._tuple[1]
michael@0 3582
michael@0 3583 def hasArgs(self):
michael@0 3584 return (len(self._tuple) == 2 and isinstance(self._tuple[1], list) or
michael@0 3585 len(self._tuple) == 3)
michael@0 3586
michael@0 3587 def args(self):
michael@0 3588 assert(self.hasArgs())
michael@0 3589 # Our args are our last element
michael@0 3590 return self._tuple[-1]
michael@0 3591
michael@0 3592 def listValue(self):
michael@0 3593 """
michael@0 3594 Backdoor for storing random data in _extendedAttrDict
michael@0 3595 """
michael@0 3596 return list(self._tuple)[1:]
michael@0 3597
michael@0 3598 # Parser
michael@0 3599
michael@0 3600 class Tokenizer(object):
michael@0 3601 tokens = [
michael@0 3602 "INTEGER",
michael@0 3603 "FLOATLITERAL",
michael@0 3604 "IDENTIFIER",
michael@0 3605 "STRING",
michael@0 3606 "WHITESPACE",
michael@0 3607 "OTHER"
michael@0 3608 ]
michael@0 3609
michael@0 3610 def t_FLOATLITERAL(self, t):
michael@0 3611 r'(-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+|Infinity))|NaN'
michael@0 3612 t.value = float(t.value)
michael@0 3613 return t
michael@0 3614
michael@0 3615 def t_INTEGER(self, t):
michael@0 3616 r'-?(0([0-7]+|[Xx][0-9A-Fa-f]+)?|[1-9][0-9]*)'
michael@0 3617 try:
michael@0 3618 # Can't use int(), because that doesn't handle octal properly.
michael@0 3619 t.value = parseInt(t.value)
michael@0 3620 except:
michael@0 3621 raise WebIDLError("Invalid integer literal",
michael@0 3622 [Location(lexer=self.lexer,
michael@0 3623 lineno=self.lexer.lineno,
michael@0 3624 lexpos=self.lexer.lexpos,
michael@0 3625 filename=self._filename)])
michael@0 3626 return t
michael@0 3627
michael@0 3628 def t_IDENTIFIER(self, t):
michael@0 3629 r'[A-Z_a-z][0-9A-Z_a-z]*'
michael@0 3630 t.type = self.keywords.get(t.value, 'IDENTIFIER')
michael@0 3631 return t
michael@0 3632
michael@0 3633 def t_STRING(self, t):
michael@0 3634 r'"[^"]*"'
michael@0 3635 t.value = t.value[1:-1]
michael@0 3636 return t
michael@0 3637
michael@0 3638 def t_WHITESPACE(self, t):
michael@0 3639 r'[\t\n\r ]+|[\t\n\r ]*((//[^\n]*|/\*.*?\*/)[\t\n\r ]*)+'
michael@0 3640 pass
michael@0 3641
michael@0 3642 def t_ELLIPSIS(self, t):
michael@0 3643 r'\.\.\.'
michael@0 3644 t.type = self.keywords.get(t.value)
michael@0 3645 return t
michael@0 3646
michael@0 3647 def t_OTHER(self, t):
michael@0 3648 r'[^\t\n\r 0-9A-Z_a-z]'
michael@0 3649 t.type = self.keywords.get(t.value, 'OTHER')
michael@0 3650 return t
michael@0 3651
michael@0 3652 keywords = {
michael@0 3653 "module": "MODULE",
michael@0 3654 "interface": "INTERFACE",
michael@0 3655 "partial": "PARTIAL",
michael@0 3656 "dictionary": "DICTIONARY",
michael@0 3657 "exception": "EXCEPTION",
michael@0 3658 "enum": "ENUM",
michael@0 3659 "callback": "CALLBACK",
michael@0 3660 "typedef": "TYPEDEF",
michael@0 3661 "implements": "IMPLEMENTS",
michael@0 3662 "const": "CONST",
michael@0 3663 "null": "NULL",
michael@0 3664 "true": "TRUE",
michael@0 3665 "false": "FALSE",
michael@0 3666 "serializer": "SERIALIZER",
michael@0 3667 "stringifier": "STRINGIFIER",
michael@0 3668 "jsonifier": "JSONIFIER",
michael@0 3669 "unrestricted": "UNRESTRICTED",
michael@0 3670 "attribute": "ATTRIBUTE",
michael@0 3671 "readonly": "READONLY",
michael@0 3672 "inherit": "INHERIT",
michael@0 3673 "static": "STATIC",
michael@0 3674 "getter": "GETTER",
michael@0 3675 "setter": "SETTER",
michael@0 3676 "creator": "CREATOR",
michael@0 3677 "deleter": "DELETER",
michael@0 3678 "legacycaller": "LEGACYCALLER",
michael@0 3679 "optional": "OPTIONAL",
michael@0 3680 "...": "ELLIPSIS",
michael@0 3681 "::": "SCOPE",
michael@0 3682 "Date": "DATE",
michael@0 3683 "DOMString": "DOMSTRING",
michael@0 3684 "ByteString": "BYTESTRING",
michael@0 3685 "any": "ANY",
michael@0 3686 "boolean": "BOOLEAN",
michael@0 3687 "byte": "BYTE",
michael@0 3688 "double": "DOUBLE",
michael@0 3689 "float": "FLOAT",
michael@0 3690 "long": "LONG",
michael@0 3691 "object": "OBJECT",
michael@0 3692 "octet": "OCTET",
michael@0 3693 "optional": "OPTIONAL",
michael@0 3694 "sequence": "SEQUENCE",
michael@0 3695 "MozMap": "MOZMAP",
michael@0 3696 "short": "SHORT",
michael@0 3697 "unsigned": "UNSIGNED",
michael@0 3698 "void": "VOID",
michael@0 3699 ":": "COLON",
michael@0 3700 ";": "SEMICOLON",
michael@0 3701 "{": "LBRACE",
michael@0 3702 "}": "RBRACE",
michael@0 3703 "(": "LPAREN",
michael@0 3704 ")": "RPAREN",
michael@0 3705 "[": "LBRACKET",
michael@0 3706 "]": "RBRACKET",
michael@0 3707 "?": "QUESTIONMARK",
michael@0 3708 ",": "COMMA",
michael@0 3709 "=": "EQUALS",
michael@0 3710 "<": "LT",
michael@0 3711 ">": "GT",
michael@0 3712 "ArrayBuffer": "ARRAYBUFFER",
michael@0 3713 "or": "OR"
michael@0 3714 }
michael@0 3715
michael@0 3716 tokens.extend(keywords.values())
michael@0 3717
michael@0 3718 def t_error(self, t):
michael@0 3719 raise WebIDLError("Unrecognized Input",
michael@0 3720 [Location(lexer=self.lexer,
michael@0 3721 lineno=self.lexer.lineno,
michael@0 3722 lexpos=self.lexer.lexpos,
michael@0 3723 filename = self.filename)])
michael@0 3724
michael@0 3725 def __init__(self, outputdir, lexer=None):
michael@0 3726 if lexer:
michael@0 3727 self.lexer = lexer
michael@0 3728 else:
michael@0 3729 self.lexer = lex.lex(object=self,
michael@0 3730 outputdir=outputdir,
michael@0 3731 lextab='webidllex',
michael@0 3732 reflags=re.DOTALL)
michael@0 3733
michael@0 3734 class Parser(Tokenizer):
michael@0 3735 def getLocation(self, p, i):
michael@0 3736 return Location(self.lexer, p.lineno(i), p.lexpos(i), self._filename)
michael@0 3737
michael@0 3738 def globalScope(self):
michael@0 3739 return self._globalScope
michael@0 3740
michael@0 3741 # The p_Foo functions here must match the WebIDL spec's grammar.
michael@0 3742 # It's acceptable to split things at '|' boundaries.
michael@0 3743 def p_Definitions(self, p):
michael@0 3744 """
michael@0 3745 Definitions : ExtendedAttributeList Definition Definitions
michael@0 3746 """
michael@0 3747 if p[2]:
michael@0 3748 p[0] = [p[2]]
michael@0 3749 p[2].addExtendedAttributes(p[1])
michael@0 3750 else:
michael@0 3751 assert not p[1]
michael@0 3752 p[0] = []
michael@0 3753
michael@0 3754 p[0].extend(p[3])
michael@0 3755
michael@0 3756 def p_DefinitionsEmpty(self, p):
michael@0 3757 """
michael@0 3758 Definitions :
michael@0 3759 """
michael@0 3760 p[0] = []
michael@0 3761
michael@0 3762 def p_Definition(self, p):
michael@0 3763 """
michael@0 3764 Definition : CallbackOrInterface
michael@0 3765 | PartialInterface
michael@0 3766 | Dictionary
michael@0 3767 | Exception
michael@0 3768 | Enum
michael@0 3769 | Typedef
michael@0 3770 | ImplementsStatement
michael@0 3771 """
michael@0 3772 p[0] = p[1]
michael@0 3773 assert p[1] # We might not have implemented something ...
michael@0 3774
michael@0 3775 def p_CallbackOrInterfaceCallback(self, p):
michael@0 3776 """
michael@0 3777 CallbackOrInterface : CALLBACK CallbackRestOrInterface
michael@0 3778 """
michael@0 3779 if p[2].isInterface():
michael@0 3780 assert isinstance(p[2], IDLInterface)
michael@0 3781 p[2].setCallback(True)
michael@0 3782
michael@0 3783 p[0] = p[2]
michael@0 3784
michael@0 3785 def p_CallbackOrInterfaceInterface(self, p):
michael@0 3786 """
michael@0 3787 CallbackOrInterface : Interface
michael@0 3788 """
michael@0 3789 p[0] = p[1]
michael@0 3790
michael@0 3791 def p_CallbackRestOrInterface(self, p):
michael@0 3792 """
michael@0 3793 CallbackRestOrInterface : CallbackRest
michael@0 3794 | Interface
michael@0 3795 """
michael@0 3796 assert p[1]
michael@0 3797 p[0] = p[1]
michael@0 3798
michael@0 3799 def p_Interface(self, p):
michael@0 3800 """
michael@0 3801 Interface : INTERFACE IDENTIFIER Inheritance LBRACE InterfaceMembers RBRACE SEMICOLON
michael@0 3802 """
michael@0 3803 location = self.getLocation(p, 1)
michael@0 3804 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
michael@0 3805 members = p[5]
michael@0 3806 parent = p[3]
michael@0 3807
michael@0 3808 try:
michael@0 3809 if self.globalScope()._lookupIdentifier(identifier):
michael@0 3810 p[0] = self.globalScope()._lookupIdentifier(identifier)
michael@0 3811 if not isinstance(p[0], IDLInterface):
michael@0 3812 raise WebIDLError("Partial interface has the same name as "
michael@0 3813 "non-interface object",
michael@0 3814 [location, p[0].location])
michael@0 3815 p[0].setNonPartial(location, parent, members)
michael@0 3816 return
michael@0 3817 except Exception, ex:
michael@0 3818 if isinstance(ex, WebIDLError):
michael@0 3819 raise ex
michael@0 3820 pass
michael@0 3821
michael@0 3822 p[0] = IDLInterface(location, self.globalScope(), identifier, parent,
michael@0 3823 members, isPartial=False)
michael@0 3824
michael@0 3825 def p_InterfaceForwardDecl(self, p):
michael@0 3826 """
michael@0 3827 Interface : INTERFACE IDENTIFIER SEMICOLON
michael@0 3828 """
michael@0 3829 location = self.getLocation(p, 1)
michael@0 3830 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
michael@0 3831
michael@0 3832 try:
michael@0 3833 if self.globalScope()._lookupIdentifier(identifier):
michael@0 3834 p[0] = self.globalScope()._lookupIdentifier(identifier)
michael@0 3835 if not isinstance(p[0], IDLExternalInterface):
michael@0 3836 raise WebIDLError("Name collision between external "
michael@0 3837 "interface declaration for identifier "
michael@0 3838 "%s and %s" % (identifier.name, p[0]),
michael@0 3839 [location, p[0].location])
michael@0 3840 return
michael@0 3841 except Exception, ex:
michael@0 3842 if isinstance(ex, WebIDLError):
michael@0 3843 raise ex
michael@0 3844 pass
michael@0 3845
michael@0 3846 p[0] = IDLExternalInterface(location, self.globalScope(), identifier)
michael@0 3847
michael@0 3848 def p_PartialInterface(self, p):
michael@0 3849 """
michael@0 3850 PartialInterface : PARTIAL INTERFACE IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
michael@0 3851 """
michael@0 3852 location = self.getLocation(p, 2)
michael@0 3853 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
michael@0 3854 members = p[5]
michael@0 3855
michael@0 3856 try:
michael@0 3857 if self.globalScope()._lookupIdentifier(identifier):
michael@0 3858 p[0] = self.globalScope()._lookupIdentifier(identifier)
michael@0 3859 if not isinstance(p[0], IDLInterface):
michael@0 3860 raise WebIDLError("Partial interface has the same name as "
michael@0 3861 "non-interface object",
michael@0 3862 [location, p[0].location])
michael@0 3863 # Just throw our members into the existing IDLInterface. If we
michael@0 3864 # have extended attributes, those will get added to it
michael@0 3865 # automatically.
michael@0 3866 p[0].members.extend(members)
michael@0 3867 return
michael@0 3868 except Exception, ex:
michael@0 3869 if isinstance(ex, WebIDLError):
michael@0 3870 raise ex
michael@0 3871 pass
michael@0 3872
michael@0 3873 p[0] = IDLInterface(location, self.globalScope(), identifier, None,
michael@0 3874 members, isPartial=True)
michael@0 3875 pass
michael@0 3876
michael@0 3877 def p_Inheritance(self, p):
michael@0 3878 """
michael@0 3879 Inheritance : COLON ScopedName
michael@0 3880 """
michael@0 3881 p[0] = IDLIdentifierPlaceholder(self.getLocation(p, 2), p[2])
michael@0 3882
michael@0 3883 def p_InheritanceEmpty(self, p):
michael@0 3884 """
michael@0 3885 Inheritance :
michael@0 3886 """
michael@0 3887 pass
michael@0 3888
michael@0 3889 def p_InterfaceMembers(self, p):
michael@0 3890 """
michael@0 3891 InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers
michael@0 3892 """
michael@0 3893 p[0] = [p[2]] if p[2] else []
michael@0 3894
michael@0 3895 assert not p[1] or p[2]
michael@0 3896 p[2].addExtendedAttributes(p[1])
michael@0 3897
michael@0 3898 p[0].extend(p[3])
michael@0 3899
michael@0 3900 def p_InterfaceMembersEmpty(self, p):
michael@0 3901 """
michael@0 3902 InterfaceMembers :
michael@0 3903 """
michael@0 3904 p[0] = []
michael@0 3905
michael@0 3906 def p_InterfaceMember(self, p):
michael@0 3907 """
michael@0 3908 InterfaceMember : Const
michael@0 3909 | AttributeOrOperation
michael@0 3910 """
michael@0 3911 p[0] = p[1]
michael@0 3912
michael@0 3913 def p_Dictionary(self, p):
michael@0 3914 """
michael@0 3915 Dictionary : DICTIONARY IDENTIFIER Inheritance LBRACE DictionaryMembers RBRACE SEMICOLON
michael@0 3916 """
michael@0 3917 location = self.getLocation(p, 1)
michael@0 3918 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
michael@0 3919 members = p[5]
michael@0 3920 p[0] = IDLDictionary(location, self.globalScope(), identifier, p[3], members)
michael@0 3921
michael@0 3922 def p_DictionaryMembers(self, p):
michael@0 3923 """
michael@0 3924 DictionaryMembers : ExtendedAttributeList DictionaryMember DictionaryMembers
michael@0 3925 |
michael@0 3926 """
michael@0 3927 if len(p) == 1:
michael@0 3928 # We're at the end of the list
michael@0 3929 p[0] = []
michael@0 3930 return
michael@0 3931 # Add our extended attributes
michael@0 3932 p[2].addExtendedAttributes(p[1])
michael@0 3933 p[0] = [p[2]]
michael@0 3934 p[0].extend(p[3])
michael@0 3935
michael@0 3936 def p_DictionaryMember(self, p):
michael@0 3937 """
michael@0 3938 DictionaryMember : Type IDENTIFIER DefaultValue SEMICOLON
michael@0 3939 """
michael@0 3940 # These quack a lot like optional arguments, so just treat them that way.
michael@0 3941 t = p[1]
michael@0 3942 assert isinstance(t, IDLType)
michael@0 3943 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
michael@0 3944 defaultValue = p[3]
michael@0 3945
michael@0 3946 p[0] = IDLArgument(self.getLocation(p, 2), identifier, t, optional=True,
michael@0 3947 defaultValue=defaultValue, variadic=False,
michael@0 3948 dictionaryMember=True)
michael@0 3949
michael@0 3950 def p_DefaultValue(self, p):
michael@0 3951 """
michael@0 3952 DefaultValue : EQUALS ConstValue
michael@0 3953 |
michael@0 3954 """
michael@0 3955 if len(p) > 1:
michael@0 3956 p[0] = p[2]
michael@0 3957 else:
michael@0 3958 p[0] = None
michael@0 3959
michael@0 3960 def p_Exception(self, p):
michael@0 3961 """
michael@0 3962 Exception : EXCEPTION IDENTIFIER Inheritance LBRACE ExceptionMembers RBRACE SEMICOLON
michael@0 3963 """
michael@0 3964 pass
michael@0 3965
michael@0 3966 def p_Enum(self, p):
michael@0 3967 """
michael@0 3968 Enum : ENUM IDENTIFIER LBRACE EnumValueList RBRACE SEMICOLON
michael@0 3969 """
michael@0 3970 location = self.getLocation(p, 1)
michael@0 3971 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
michael@0 3972
michael@0 3973 values = p[4]
michael@0 3974 assert values
michael@0 3975 p[0] = IDLEnum(location, self.globalScope(), identifier, values)
michael@0 3976
michael@0 3977 def p_EnumValueList(self, p):
michael@0 3978 """
michael@0 3979 EnumValueList : STRING EnumValueListComma
michael@0 3980 """
michael@0 3981 p[0] = [p[1]]
michael@0 3982 p[0].extend(p[2])
michael@0 3983
michael@0 3984 def p_EnumValueListComma(self, p):
michael@0 3985 """
michael@0 3986 EnumValueListComma : COMMA EnumValueListString
michael@0 3987 """
michael@0 3988 p[0] = p[2]
michael@0 3989
michael@0 3990 def p_EnumValueListCommaEmpty(self, p):
michael@0 3991 """
michael@0 3992 EnumValueListComma :
michael@0 3993 """
michael@0 3994 p[0] = []
michael@0 3995
michael@0 3996 def p_EnumValueListString(self, p):
michael@0 3997 """
michael@0 3998 EnumValueListString : STRING EnumValueListComma
michael@0 3999 """
michael@0 4000 p[0] = [p[1]]
michael@0 4001 p[0].extend(p[2])
michael@0 4002
michael@0 4003 def p_EnumValueListStringEmpty(self, p):
michael@0 4004 """
michael@0 4005 EnumValueListString :
michael@0 4006 """
michael@0 4007 p[0] = []
michael@0 4008
michael@0 4009 def p_CallbackRest(self, p):
michael@0 4010 """
michael@0 4011 CallbackRest : IDENTIFIER EQUALS ReturnType LPAREN ArgumentList RPAREN SEMICOLON
michael@0 4012 """
michael@0 4013 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
michael@0 4014 p[0] = IDLCallbackType(self.getLocation(p, 1), self.globalScope(),
michael@0 4015 identifier, p[3], p[5])
michael@0 4016
michael@0 4017 def p_ExceptionMembers(self, p):
michael@0 4018 """
michael@0 4019 ExceptionMembers : ExtendedAttributeList ExceptionMember ExceptionMembers
michael@0 4020 |
michael@0 4021 """
michael@0 4022 pass
michael@0 4023
michael@0 4024 def p_Typedef(self, p):
michael@0 4025 """
michael@0 4026 Typedef : TYPEDEF Type IDENTIFIER SEMICOLON
michael@0 4027 """
michael@0 4028 typedef = IDLTypedefType(self.getLocation(p, 1), p[2], p[3])
michael@0 4029 typedef.resolve(self.globalScope())
michael@0 4030 p[0] = typedef
michael@0 4031
michael@0 4032 def p_ImplementsStatement(self, p):
michael@0 4033 """
michael@0 4034 ImplementsStatement : ScopedName IMPLEMENTS ScopedName SEMICOLON
michael@0 4035 """
michael@0 4036 assert(p[2] == "implements")
michael@0 4037 implementor = IDLIdentifierPlaceholder(self.getLocation(p, 1), p[1])
michael@0 4038 implementee = IDLIdentifierPlaceholder(self.getLocation(p, 3), p[3])
michael@0 4039 p[0] = IDLImplementsStatement(self.getLocation(p, 1), implementor,
michael@0 4040 implementee)
michael@0 4041
michael@0 4042 def p_Const(self, p):
michael@0 4043 """
michael@0 4044 Const : CONST ConstType IDENTIFIER EQUALS ConstValue SEMICOLON
michael@0 4045 """
michael@0 4046 location = self.getLocation(p, 1)
michael@0 4047 type = p[2]
michael@0 4048 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
michael@0 4049 value = p[5]
michael@0 4050 p[0] = IDLConst(location, identifier, type, value)
michael@0 4051
michael@0 4052 def p_ConstValueBoolean(self, p):
michael@0 4053 """
michael@0 4054 ConstValue : BooleanLiteral
michael@0 4055 """
michael@0 4056 location = self.getLocation(p, 1)
michael@0 4057 booleanType = BuiltinTypes[IDLBuiltinType.Types.boolean]
michael@0 4058 p[0] = IDLValue(location, booleanType, p[1])
michael@0 4059
michael@0 4060 def p_ConstValueInteger(self, p):
michael@0 4061 """
michael@0 4062 ConstValue : INTEGER
michael@0 4063 """
michael@0 4064 location = self.getLocation(p, 1)
michael@0 4065
michael@0 4066 # We don't know ahead of time what type the integer literal is.
michael@0 4067 # Determine the smallest type it could possibly fit in and use that.
michael@0 4068 integerType = matchIntegerValueToType(p[1])
michael@0 4069 if integerType == None:
michael@0 4070 raise WebIDLError("Integer literal out of range", [location])
michael@0 4071
michael@0 4072 p[0] = IDLValue(location, integerType, p[1])
michael@0 4073
michael@0 4074 def p_ConstValueFloat(self, p):
michael@0 4075 """
michael@0 4076 ConstValue : FLOATLITERAL
michael@0 4077 """
michael@0 4078 location = self.getLocation(p, 1)
michael@0 4079 p[0] = IDLValue(location, BuiltinTypes[IDLBuiltinType.Types.unrestricted_float], p[1])
michael@0 4080
michael@0 4081 def p_ConstValueString(self, p):
michael@0 4082 """
michael@0 4083 ConstValue : STRING
michael@0 4084 """
michael@0 4085 location = self.getLocation(p, 1)
michael@0 4086 stringType = BuiltinTypes[IDLBuiltinType.Types.domstring]
michael@0 4087 p[0] = IDLValue(location, stringType, p[1])
michael@0 4088
michael@0 4089 def p_ConstValueNull(self, p):
michael@0 4090 """
michael@0 4091 ConstValue : NULL
michael@0 4092 """
michael@0 4093 p[0] = IDLNullValue(self.getLocation(p, 1))
michael@0 4094
michael@0 4095 def p_BooleanLiteralTrue(self, p):
michael@0 4096 """
michael@0 4097 BooleanLiteral : TRUE
michael@0 4098 """
michael@0 4099 p[0] = True
michael@0 4100
michael@0 4101 def p_BooleanLiteralFalse(self, p):
michael@0 4102 """
michael@0 4103 BooleanLiteral : FALSE
michael@0 4104 """
michael@0 4105 p[0] = False
michael@0 4106
michael@0 4107 def p_AttributeOrOperation(self, p):
michael@0 4108 """
michael@0 4109 AttributeOrOperation : Attribute
michael@0 4110 | Operation
michael@0 4111 """
michael@0 4112 p[0] = p[1]
michael@0 4113
michael@0 4114 def p_AttributeWithQualifier(self, p):
michael@0 4115 """
michael@0 4116 Attribute : Qualifier AttributeRest
michael@0 4117 """
michael@0 4118 static = IDLInterfaceMember.Special.Static in p[1]
michael@0 4119 stringifier = IDLInterfaceMember.Special.Stringifier in p[1]
michael@0 4120 (location, identifier, type, readonly) = p[2]
michael@0 4121 p[0] = IDLAttribute(location, identifier, type, readonly, static=static,
michael@0 4122 stringifier=stringifier)
michael@0 4123
michael@0 4124 def p_Attribute(self, p):
michael@0 4125 """
michael@0 4126 Attribute : Inherit AttributeRest
michael@0 4127 """
michael@0 4128 (location, identifier, type, readonly) = p[2]
michael@0 4129 p[0] = IDLAttribute(location, identifier, type, readonly, inherit=p[1])
michael@0 4130
michael@0 4131 def p_AttributeRest(self, p):
michael@0 4132 """
michael@0 4133 AttributeRest : ReadOnly ATTRIBUTE Type IDENTIFIER SEMICOLON
michael@0 4134 """
michael@0 4135 location = self.getLocation(p, 2)
michael@0 4136 readonly = p[1]
michael@0 4137 t = p[3]
michael@0 4138 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 4), p[4])
michael@0 4139 p[0] = (location, identifier, t, readonly)
michael@0 4140
michael@0 4141 def p_ReadOnly(self, p):
michael@0 4142 """
michael@0 4143 ReadOnly : READONLY
michael@0 4144 """
michael@0 4145 p[0] = True
michael@0 4146
michael@0 4147 def p_ReadOnlyEmpty(self, p):
michael@0 4148 """
michael@0 4149 ReadOnly :
michael@0 4150 """
michael@0 4151 p[0] = False
michael@0 4152
michael@0 4153 def p_Inherit(self, p):
michael@0 4154 """
michael@0 4155 Inherit : INHERIT
michael@0 4156 """
michael@0 4157 p[0] = True
michael@0 4158
michael@0 4159 def p_InheritEmpty(self, p):
michael@0 4160 """
michael@0 4161 Inherit :
michael@0 4162 """
michael@0 4163 p[0] = False
michael@0 4164
michael@0 4165 def p_Operation(self, p):
michael@0 4166 """
michael@0 4167 Operation : Qualifiers OperationRest
michael@0 4168 """
michael@0 4169 qualifiers = p[1]
michael@0 4170
michael@0 4171 # Disallow duplicates in the qualifier set
michael@0 4172 if not len(set(qualifiers)) == len(qualifiers):
michael@0 4173 raise WebIDLError("Duplicate qualifiers are not allowed",
michael@0 4174 [self.getLocation(p, 1)])
michael@0 4175
michael@0 4176 static = IDLInterfaceMember.Special.Static in p[1]
michael@0 4177 # If static is there that's all that's allowed. This is disallowed
michael@0 4178 # by the parser, so we can assert here.
michael@0 4179 assert not static or len(qualifiers) == 1
michael@0 4180
michael@0 4181 stringifier = IDLInterfaceMember.Special.Stringifier in p[1]
michael@0 4182 # If stringifier is there that's all that's allowed. This is disallowed
michael@0 4183 # by the parser, so we can assert here.
michael@0 4184 assert not stringifier or len(qualifiers) == 1
michael@0 4185
michael@0 4186 getter = True if IDLMethod.Special.Getter in p[1] else False
michael@0 4187 setter = True if IDLMethod.Special.Setter in p[1] else False
michael@0 4188 creator = True if IDLMethod.Special.Creator in p[1] else False
michael@0 4189 deleter = True if IDLMethod.Special.Deleter in p[1] else False
michael@0 4190 legacycaller = True if IDLMethod.Special.LegacyCaller in p[1] else False
michael@0 4191
michael@0 4192 if getter or deleter:
michael@0 4193 if setter or creator:
michael@0 4194 raise WebIDLError("getter and deleter are incompatible with setter and creator",
michael@0 4195 [self.getLocation(p, 1)])
michael@0 4196
michael@0 4197 (returnType, identifier, arguments) = p[2]
michael@0 4198
michael@0 4199 assert isinstance(returnType, IDLType)
michael@0 4200
michael@0 4201 specialType = IDLMethod.NamedOrIndexed.Neither
michael@0 4202
michael@0 4203 if getter or deleter:
michael@0 4204 if len(arguments) != 1:
michael@0 4205 raise WebIDLError("%s has wrong number of arguments" %
michael@0 4206 ("getter" if getter else "deleter"),
michael@0 4207 [self.getLocation(p, 2)])
michael@0 4208 argType = arguments[0].type
michael@0 4209 if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]:
michael@0 4210 specialType = IDLMethod.NamedOrIndexed.Named
michael@0 4211 elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]:
michael@0 4212 specialType = IDLMethod.NamedOrIndexed.Indexed
michael@0 4213 else:
michael@0 4214 raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" %
michael@0 4215 ("getter" if getter else "deleter"),
michael@0 4216 [arguments[0].location])
michael@0 4217 if arguments[0].optional or arguments[0].variadic:
michael@0 4218 raise WebIDLError("%s cannot have %s argument" %
michael@0 4219 ("getter" if getter else "deleter",
michael@0 4220 "optional" if arguments[0].optional else "variadic"),
michael@0 4221 [arguments[0].location])
michael@0 4222 if getter:
michael@0 4223 if returnType.isVoid():
michael@0 4224 raise WebIDLError("getter cannot have void return type",
michael@0 4225 [self.getLocation(p, 2)])
michael@0 4226 if setter or creator:
michael@0 4227 if len(arguments) != 2:
michael@0 4228 raise WebIDLError("%s has wrong number of arguments" %
michael@0 4229 ("setter" if setter else "creator"),
michael@0 4230 [self.getLocation(p, 2)])
michael@0 4231 argType = arguments[0].type
michael@0 4232 if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]:
michael@0 4233 specialType = IDLMethod.NamedOrIndexed.Named
michael@0 4234 elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]:
michael@0 4235 specialType = IDLMethod.NamedOrIndexed.Indexed
michael@0 4236 else:
michael@0 4237 raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" %
michael@0 4238 ("setter" if setter else "creator"),
michael@0 4239 [arguments[0].location])
michael@0 4240 if arguments[0].optional or arguments[0].variadic:
michael@0 4241 raise WebIDLError("%s cannot have %s argument" %
michael@0 4242 ("setter" if setter else "creator",
michael@0 4243 "optional" if arguments[0].optional else "variadic"),
michael@0 4244 [arguments[0].location])
michael@0 4245 if arguments[1].optional or arguments[1].variadic:
michael@0 4246 raise WebIDLError("%s cannot have %s argument" %
michael@0 4247 ("setter" if setter else "creator",
michael@0 4248 "optional" if arguments[1].optional else "variadic"),
michael@0 4249 [arguments[1].location])
michael@0 4250
michael@0 4251 if stringifier:
michael@0 4252 if len(arguments) != 0:
michael@0 4253 raise WebIDLError("stringifier has wrong number of arguments",
michael@0 4254 [self.getLocation(p, 2)])
michael@0 4255 if not returnType.isDOMString():
michael@0 4256 raise WebIDLError("stringifier must have DOMString return type",
michael@0 4257 [self.getLocation(p, 2)])
michael@0 4258
michael@0 4259 # identifier might be None. This is only permitted for special methods.
michael@0 4260 if not identifier:
michael@0 4261 if not getter and not setter and not creator and \
michael@0 4262 not deleter and not legacycaller and not stringifier:
michael@0 4263 raise WebIDLError("Identifier required for non-special methods",
michael@0 4264 [self.getLocation(p, 2)])
michael@0 4265
michael@0 4266 location = BuiltinLocation("<auto-generated-identifier>")
michael@0 4267 identifier = IDLUnresolvedIdentifier(location, "__%s%s%s%s%s%s%s" %
michael@0 4268 ("named" if specialType == IDLMethod.NamedOrIndexed.Named else \
michael@0 4269 "indexed" if specialType == IDLMethod.NamedOrIndexed.Indexed else "",
michael@0 4270 "getter" if getter else "",
michael@0 4271 "setter" if setter else "",
michael@0 4272 "deleter" if deleter else "",
michael@0 4273 "creator" if creator else "",
michael@0 4274 "legacycaller" if legacycaller else "",
michael@0 4275 "stringifier" if stringifier else ""), allowDoubleUnderscore=True)
michael@0 4276
michael@0 4277 method = IDLMethod(self.getLocation(p, 2), identifier, returnType, arguments,
michael@0 4278 static=static, getter=getter, setter=setter, creator=creator,
michael@0 4279 deleter=deleter, specialType=specialType,
michael@0 4280 legacycaller=legacycaller, stringifier=stringifier)
michael@0 4281 p[0] = method
michael@0 4282
michael@0 4283 def p_Stringifier(self, p):
michael@0 4284 """
michael@0 4285 Operation : STRINGIFIER SEMICOLON
michael@0 4286 """
michael@0 4287 identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
michael@0 4288 "__stringifier",
michael@0 4289 allowDoubleUnderscore=True)
michael@0 4290 method = IDLMethod(self.getLocation(p, 1),
michael@0 4291 identifier,
michael@0 4292 returnType=BuiltinTypes[IDLBuiltinType.Types.domstring],
michael@0 4293 arguments=[],
michael@0 4294 stringifier=True)
michael@0 4295 p[0] = method
michael@0 4296
michael@0 4297 def p_Jsonifier(self, p):
michael@0 4298 """
michael@0 4299 Operation : JSONIFIER SEMICOLON
michael@0 4300 """
michael@0 4301 identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
michael@0 4302 "__jsonifier", allowDoubleUnderscore=True)
michael@0 4303 method = IDLMethod(self.getLocation(p, 1),
michael@0 4304 identifier,
michael@0 4305 returnType=BuiltinTypes[IDLBuiltinType.Types.object],
michael@0 4306 arguments=[],
michael@0 4307 jsonifier=True)
michael@0 4308 p[0] = method
michael@0 4309
michael@0 4310 def p_QualifierStatic(self, p):
michael@0 4311 """
michael@0 4312 Qualifier : STATIC
michael@0 4313 """
michael@0 4314 p[0] = [IDLInterfaceMember.Special.Static]
michael@0 4315
michael@0 4316 def p_QualifierStringifier(self, p):
michael@0 4317 """
michael@0 4318 Qualifier : STRINGIFIER
michael@0 4319 """
michael@0 4320 p[0] = [IDLInterfaceMember.Special.Stringifier]
michael@0 4321
michael@0 4322 def p_Qualifiers(self, p):
michael@0 4323 """
michael@0 4324 Qualifiers : Qualifier
michael@0 4325 | Specials
michael@0 4326 """
michael@0 4327 p[0] = p[1]
michael@0 4328
michael@0 4329 def p_Specials(self, p):
michael@0 4330 """
michael@0 4331 Specials : Special Specials
michael@0 4332 """
michael@0 4333 p[0] = [p[1]]
michael@0 4334 p[0].extend(p[2])
michael@0 4335
michael@0 4336 def p_SpecialsEmpty(self, p):
michael@0 4337 """
michael@0 4338 Specials :
michael@0 4339 """
michael@0 4340 p[0] = []
michael@0 4341
michael@0 4342 def p_SpecialGetter(self, p):
michael@0 4343 """
michael@0 4344 Special : GETTER
michael@0 4345 """
michael@0 4346 p[0] = IDLMethod.Special.Getter
michael@0 4347
michael@0 4348 def p_SpecialSetter(self, p):
michael@0 4349 """
michael@0 4350 Special : SETTER
michael@0 4351 """
michael@0 4352 p[0] = IDLMethod.Special.Setter
michael@0 4353
michael@0 4354 def p_SpecialCreator(self, p):
michael@0 4355 """
michael@0 4356 Special : CREATOR
michael@0 4357 """
michael@0 4358 p[0] = IDLMethod.Special.Creator
michael@0 4359
michael@0 4360 def p_SpecialDeleter(self, p):
michael@0 4361 """
michael@0 4362 Special : DELETER
michael@0 4363 """
michael@0 4364 p[0] = IDLMethod.Special.Deleter
michael@0 4365
michael@0 4366 def p_SpecialLegacyCaller(self, p):
michael@0 4367 """
michael@0 4368 Special : LEGACYCALLER
michael@0 4369 """
michael@0 4370 p[0] = IDLMethod.Special.LegacyCaller
michael@0 4371
michael@0 4372 def p_OperationRest(self, p):
michael@0 4373 """
michael@0 4374 OperationRest : ReturnType OptionalIdentifier LPAREN ArgumentList RPAREN SEMICOLON
michael@0 4375 """
michael@0 4376 p[0] = (p[1], p[2], p[4])
michael@0 4377
michael@0 4378 def p_OptionalIdentifier(self, p):
michael@0 4379 """
michael@0 4380 OptionalIdentifier : IDENTIFIER
michael@0 4381 """
michael@0 4382 p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
michael@0 4383
michael@0 4384 def p_OptionalIdentifierEmpty(self, p):
michael@0 4385 """
michael@0 4386 OptionalIdentifier :
michael@0 4387 """
michael@0 4388 pass
michael@0 4389
michael@0 4390 def p_ArgumentList(self, p):
michael@0 4391 """
michael@0 4392 ArgumentList : Argument Arguments
michael@0 4393 """
michael@0 4394 p[0] = [p[1]] if p[1] else []
michael@0 4395 p[0].extend(p[2])
michael@0 4396
michael@0 4397 def p_ArgumentListEmpty(self, p):
michael@0 4398 """
michael@0 4399 ArgumentList :
michael@0 4400 """
michael@0 4401 p[0] = []
michael@0 4402
michael@0 4403 def p_Arguments(self, p):
michael@0 4404 """
michael@0 4405 Arguments : COMMA Argument Arguments
michael@0 4406 """
michael@0 4407 p[0] = [p[2]] if p[2] else []
michael@0 4408 p[0].extend(p[3])
michael@0 4409
michael@0 4410 def p_ArgumentsEmpty(self, p):
michael@0 4411 """
michael@0 4412 Arguments :
michael@0 4413 """
michael@0 4414 p[0] = []
michael@0 4415
michael@0 4416 def p_Argument(self, p):
michael@0 4417 """
michael@0 4418 Argument : ExtendedAttributeList Optional Type Ellipsis ArgumentName DefaultValue
michael@0 4419 """
michael@0 4420 t = p[3]
michael@0 4421 assert isinstance(t, IDLType)
michael@0 4422 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 5), p[5])
michael@0 4423
michael@0 4424 optional = p[2]
michael@0 4425 variadic = p[4]
michael@0 4426 defaultValue = p[6]
michael@0 4427
michael@0 4428 if not optional and defaultValue:
michael@0 4429 raise WebIDLError("Mandatory arguments can't have a default value.",
michael@0 4430 [self.getLocation(p, 6)])
michael@0 4431
michael@0 4432 # We can't test t.isAny() here and give it a default value as needed,
michael@0 4433 # since at this point t is not a fully resolved type yet (e.g. it might
michael@0 4434 # be a typedef). We'll handle the 'any' case in IDLArgument.complete.
michael@0 4435
michael@0 4436 if variadic:
michael@0 4437 if optional:
michael@0 4438 raise WebIDLError("Variadic arguments should not be marked optional.",
michael@0 4439 [self.getLocation(p, 2)])
michael@0 4440 optional = variadic
michael@0 4441
michael@0 4442 p[0] = IDLArgument(self.getLocation(p, 5), identifier, t, optional, defaultValue, variadic)
michael@0 4443 p[0].addExtendedAttributes(p[1])
michael@0 4444
michael@0 4445 def p_ArgumentName(self, p):
michael@0 4446 """
michael@0 4447 ArgumentName : IDENTIFIER
michael@0 4448 | ATTRIBUTE
michael@0 4449 | CALLBACK
michael@0 4450 | CONST
michael@0 4451 | CREATOR
michael@0 4452 | DELETER
michael@0 4453 | DICTIONARY
michael@0 4454 | ENUM
michael@0 4455 | EXCEPTION
michael@0 4456 | GETTER
michael@0 4457 | IMPLEMENTS
michael@0 4458 | INHERIT
michael@0 4459 | INTERFACE
michael@0 4460 | LEGACYCALLER
michael@0 4461 | PARTIAL
michael@0 4462 | SERIALIZER
michael@0 4463 | SETTER
michael@0 4464 | STATIC
michael@0 4465 | STRINGIFIER
michael@0 4466 | JSONIFIER
michael@0 4467 | TYPEDEF
michael@0 4468 | UNRESTRICTED
michael@0 4469 """
michael@0 4470 p[0] = p[1]
michael@0 4471
michael@0 4472 def p_Optional(self, p):
michael@0 4473 """
michael@0 4474 Optional : OPTIONAL
michael@0 4475 """
michael@0 4476 p[0] = True
michael@0 4477
michael@0 4478 def p_OptionalEmpty(self, p):
michael@0 4479 """
michael@0 4480 Optional :
michael@0 4481 """
michael@0 4482 p[0] = False
michael@0 4483
michael@0 4484 def p_Ellipsis(self, p):
michael@0 4485 """
michael@0 4486 Ellipsis : ELLIPSIS
michael@0 4487 """
michael@0 4488 p[0] = True
michael@0 4489
michael@0 4490 def p_EllipsisEmpty(self, p):
michael@0 4491 """
michael@0 4492 Ellipsis :
michael@0 4493 """
michael@0 4494 p[0] = False
michael@0 4495
michael@0 4496 def p_ExceptionMember(self, p):
michael@0 4497 """
michael@0 4498 ExceptionMember : Const
michael@0 4499 | ExceptionField
michael@0 4500 """
michael@0 4501 pass
michael@0 4502
michael@0 4503 def p_ExceptionField(self, p):
michael@0 4504 """
michael@0 4505 ExceptionField : Type IDENTIFIER SEMICOLON
michael@0 4506 """
michael@0 4507 pass
michael@0 4508
michael@0 4509 def p_ExtendedAttributeList(self, p):
michael@0 4510 """
michael@0 4511 ExtendedAttributeList : LBRACKET ExtendedAttribute ExtendedAttributes RBRACKET
michael@0 4512 """
michael@0 4513 p[0] = [p[2]]
michael@0 4514 if p[3]:
michael@0 4515 p[0].extend(p[3])
michael@0 4516
michael@0 4517 def p_ExtendedAttributeListEmpty(self, p):
michael@0 4518 """
michael@0 4519 ExtendedAttributeList :
michael@0 4520 """
michael@0 4521 p[0] = []
michael@0 4522
michael@0 4523 def p_ExtendedAttribute(self, p):
michael@0 4524 """
michael@0 4525 ExtendedAttribute : ExtendedAttributeNoArgs
michael@0 4526 | ExtendedAttributeArgList
michael@0 4527 | ExtendedAttributeIdent
michael@0 4528 | ExtendedAttributeNamedArgList
michael@0 4529 """
michael@0 4530 p[0] = IDLExtendedAttribute(self.getLocation(p, 1), p[1])
michael@0 4531
michael@0 4532 def p_ExtendedAttributeEmpty(self, p):
michael@0 4533 """
michael@0 4534 ExtendedAttribute :
michael@0 4535 """
michael@0 4536 pass
michael@0 4537
michael@0 4538 def p_ExtendedAttributes(self, p):
michael@0 4539 """
michael@0 4540 ExtendedAttributes : COMMA ExtendedAttribute ExtendedAttributes
michael@0 4541 """
michael@0 4542 p[0] = [p[2]] if p[2] else []
michael@0 4543 p[0].extend(p[3])
michael@0 4544
michael@0 4545 def p_ExtendedAttributesEmpty(self, p):
michael@0 4546 """
michael@0 4547 ExtendedAttributes :
michael@0 4548 """
michael@0 4549 p[0] = []
michael@0 4550
michael@0 4551 def p_Other(self, p):
michael@0 4552 """
michael@0 4553 Other : INTEGER
michael@0 4554 | FLOATLITERAL
michael@0 4555 | IDENTIFIER
michael@0 4556 | STRING
michael@0 4557 | OTHER
michael@0 4558 | ELLIPSIS
michael@0 4559 | COLON
michael@0 4560 | SCOPE
michael@0 4561 | SEMICOLON
michael@0 4562 | LT
michael@0 4563 | EQUALS
michael@0 4564 | GT
michael@0 4565 | QUESTIONMARK
michael@0 4566 | DATE
michael@0 4567 | DOMSTRING
michael@0 4568 | BYTESTRING
michael@0 4569 | ANY
michael@0 4570 | ATTRIBUTE
michael@0 4571 | BOOLEAN
michael@0 4572 | BYTE
michael@0 4573 | LEGACYCALLER
michael@0 4574 | CONST
michael@0 4575 | CREATOR
michael@0 4576 | DELETER
michael@0 4577 | DOUBLE
michael@0 4578 | EXCEPTION
michael@0 4579 | FALSE
michael@0 4580 | FLOAT
michael@0 4581 | GETTER
michael@0 4582 | IMPLEMENTS
michael@0 4583 | INHERIT
michael@0 4584 | INTERFACE
michael@0 4585 | LONG
michael@0 4586 | MODULE
michael@0 4587 | NULL
michael@0 4588 | OBJECT
michael@0 4589 | OCTET
michael@0 4590 | OPTIONAL
michael@0 4591 | SEQUENCE
michael@0 4592 | MOZMAP
michael@0 4593 | SETTER
michael@0 4594 | SHORT
michael@0 4595 | STATIC
michael@0 4596 | STRINGIFIER
michael@0 4597 | JSONIFIER
michael@0 4598 | TRUE
michael@0 4599 | TYPEDEF
michael@0 4600 | UNSIGNED
michael@0 4601 | VOID
michael@0 4602 """
michael@0 4603 pass
michael@0 4604
michael@0 4605 def p_OtherOrComma(self, p):
michael@0 4606 """
michael@0 4607 OtherOrComma : Other
michael@0 4608 | COMMA
michael@0 4609 """
michael@0 4610 pass
michael@0 4611
michael@0 4612 def p_TypeSingleType(self, p):
michael@0 4613 """
michael@0 4614 Type : SingleType
michael@0 4615 """
michael@0 4616 p[0] = p[1]
michael@0 4617
michael@0 4618 def p_TypeUnionType(self, p):
michael@0 4619 """
michael@0 4620 Type : UnionType TypeSuffix
michael@0 4621 """
michael@0 4622 p[0] = self.handleModifiers(p[1], p[2])
michael@0 4623
michael@0 4624 def p_SingleTypeNonAnyType(self, p):
michael@0 4625 """
michael@0 4626 SingleType : NonAnyType
michael@0 4627 """
michael@0 4628 p[0] = p[1]
michael@0 4629
michael@0 4630 def p_SingleTypeAnyType(self, p):
michael@0 4631 """
michael@0 4632 SingleType : ANY TypeSuffixStartingWithArray
michael@0 4633 """
michael@0 4634 p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.any], p[2])
michael@0 4635
michael@0 4636 def p_UnionType(self, p):
michael@0 4637 """
michael@0 4638 UnionType : LPAREN UnionMemberType OR UnionMemberType UnionMemberTypes RPAREN
michael@0 4639 """
michael@0 4640 types = [p[2], p[4]]
michael@0 4641 types.extend(p[5])
michael@0 4642 p[0] = IDLUnionType(self.getLocation(p, 1), types)
michael@0 4643
michael@0 4644 def p_UnionMemberTypeNonAnyType(self, p):
michael@0 4645 """
michael@0 4646 UnionMemberType : NonAnyType
michael@0 4647 """
michael@0 4648 p[0] = p[1]
michael@0 4649
michael@0 4650 def p_UnionMemberTypeArrayOfAny(self, p):
michael@0 4651 """
michael@0 4652 UnionMemberTypeArrayOfAny : ANY LBRACKET RBRACKET
michael@0 4653 """
michael@0 4654 p[0] = IDLArrayType(self.getLocation(p, 2),
michael@0 4655 BuiltinTypes[IDLBuiltinType.Types.any])
michael@0 4656
michael@0 4657 def p_UnionMemberType(self, p):
michael@0 4658 """
michael@0 4659 UnionMemberType : UnionType TypeSuffix
michael@0 4660 | UnionMemberTypeArrayOfAny TypeSuffix
michael@0 4661 """
michael@0 4662 p[0] = self.handleModifiers(p[1], p[2])
michael@0 4663
michael@0 4664 def p_UnionMemberTypes(self, p):
michael@0 4665 """
michael@0 4666 UnionMemberTypes : OR UnionMemberType UnionMemberTypes
michael@0 4667 """
michael@0 4668 p[0] = [p[2]]
michael@0 4669 p[0].extend(p[3])
michael@0 4670
michael@0 4671 def p_UnionMemberTypesEmpty(self, p):
michael@0 4672 """
michael@0 4673 UnionMemberTypes :
michael@0 4674 """
michael@0 4675 p[0] = []
michael@0 4676
michael@0 4677 def p_NonAnyType(self, p):
michael@0 4678 """
michael@0 4679 NonAnyType : PrimitiveOrStringType TypeSuffix
michael@0 4680 | ARRAYBUFFER TypeSuffix
michael@0 4681 | OBJECT TypeSuffix
michael@0 4682 """
michael@0 4683 if p[1] == "object":
michael@0 4684 type = BuiltinTypes[IDLBuiltinType.Types.object]
michael@0 4685 elif p[1] == "ArrayBuffer":
michael@0 4686 type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer]
michael@0 4687 else:
michael@0 4688 type = BuiltinTypes[p[1]]
michael@0 4689
michael@0 4690 p[0] = self.handleModifiers(type, p[2])
michael@0 4691
michael@0 4692 def p_NonAnyTypeSequenceType(self, p):
michael@0 4693 """
michael@0 4694 NonAnyType : SEQUENCE LT Type GT Null
michael@0 4695 """
michael@0 4696 innerType = p[3]
michael@0 4697 type = IDLSequenceType(self.getLocation(p, 1), innerType)
michael@0 4698 if p[5]:
michael@0 4699 type = IDLNullableType(self.getLocation(p, 5), type)
michael@0 4700 p[0] = type
michael@0 4701
michael@0 4702 def p_NonAnyTypeMozMapType(self, p):
michael@0 4703 """
michael@0 4704 NonAnyType : MOZMAP LT Type GT Null
michael@0 4705 """
michael@0 4706 innerType = p[3]
michael@0 4707 type = IDLMozMapType(self.getLocation(p, 1), innerType)
michael@0 4708 if p[5]:
michael@0 4709 type = IDLNullableType(self.getLocation(p, 5), type)
michael@0 4710 p[0] = type
michael@0 4711
michael@0 4712 def p_NonAnyTypeScopedName(self, p):
michael@0 4713 """
michael@0 4714 NonAnyType : ScopedName TypeSuffix
michael@0 4715 """
michael@0 4716 assert isinstance(p[1], IDLUnresolvedIdentifier)
michael@0 4717
michael@0 4718 type = None
michael@0 4719
michael@0 4720 try:
michael@0 4721 if self.globalScope()._lookupIdentifier(p[1]):
michael@0 4722 obj = self.globalScope()._lookupIdentifier(p[1])
michael@0 4723 if obj.isType():
michael@0 4724 type = obj
michael@0 4725 else:
michael@0 4726 type = IDLWrapperType(self.getLocation(p, 1), p[1])
michael@0 4727 p[0] = self.handleModifiers(type, p[2])
michael@0 4728 return
michael@0 4729 except:
michael@0 4730 pass
michael@0 4731
michael@0 4732 type = IDLUnresolvedType(self.getLocation(p, 1), p[1])
michael@0 4733 p[0] = self.handleModifiers(type, p[2])
michael@0 4734
michael@0 4735 def p_NonAnyTypeDate(self, p):
michael@0 4736 """
michael@0 4737 NonAnyType : DATE TypeSuffix
michael@0 4738 """
michael@0 4739 p[0] = self.handleModifiers(BuiltinTypes[IDLBuiltinType.Types.date],
michael@0 4740 p[2])
michael@0 4741
michael@0 4742 def p_ConstType(self, p):
michael@0 4743 """
michael@0 4744 ConstType : PrimitiveOrStringType Null
michael@0 4745 """
michael@0 4746 type = BuiltinTypes[p[1]]
michael@0 4747 if p[2]:
michael@0 4748 type = IDLNullableType(self.getLocation(p, 1), type)
michael@0 4749 p[0] = type
michael@0 4750
michael@0 4751 def p_ConstTypeIdentifier(self, p):
michael@0 4752 """
michael@0 4753 ConstType : IDENTIFIER Null
michael@0 4754 """
michael@0 4755 identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
michael@0 4756
michael@0 4757 type = IDLUnresolvedType(self.getLocation(p, 1), identifier)
michael@0 4758 if p[2]:
michael@0 4759 type = IDLNullableType(self.getLocation(p, 1), type)
michael@0 4760 p[0] = type
michael@0 4761
michael@0 4762 def p_PrimitiveOrStringTypeUint(self, p):
michael@0 4763 """
michael@0 4764 PrimitiveOrStringType : UnsignedIntegerType
michael@0 4765 """
michael@0 4766 p[0] = p[1]
michael@0 4767
michael@0 4768 def p_PrimitiveOrStringTypeBoolean(self, p):
michael@0 4769 """
michael@0 4770 PrimitiveOrStringType : BOOLEAN
michael@0 4771 """
michael@0 4772 p[0] = IDLBuiltinType.Types.boolean
michael@0 4773
michael@0 4774 def p_PrimitiveOrStringTypeByte(self, p):
michael@0 4775 """
michael@0 4776 PrimitiveOrStringType : BYTE
michael@0 4777 """
michael@0 4778 p[0] = IDLBuiltinType.Types.byte
michael@0 4779
michael@0 4780 def p_PrimitiveOrStringTypeOctet(self, p):
michael@0 4781 """
michael@0 4782 PrimitiveOrStringType : OCTET
michael@0 4783 """
michael@0 4784 p[0] = IDLBuiltinType.Types.octet
michael@0 4785
michael@0 4786 def p_PrimitiveOrStringTypeFloat(self, p):
michael@0 4787 """
michael@0 4788 PrimitiveOrStringType : FLOAT
michael@0 4789 """
michael@0 4790 p[0] = IDLBuiltinType.Types.float
michael@0 4791
michael@0 4792 def p_PrimitiveOrStringTypeUnrestictedFloat(self, p):
michael@0 4793 """
michael@0 4794 PrimitiveOrStringType : UNRESTRICTED FLOAT
michael@0 4795 """
michael@0 4796 p[0] = IDLBuiltinType.Types.unrestricted_float
michael@0 4797
michael@0 4798 def p_PrimitiveOrStringTypeDouble(self, p):
michael@0 4799 """
michael@0 4800 PrimitiveOrStringType : DOUBLE
michael@0 4801 """
michael@0 4802 p[0] = IDLBuiltinType.Types.double
michael@0 4803
michael@0 4804 def p_PrimitiveOrStringTypeUnrestictedDouble(self, p):
michael@0 4805 """
michael@0 4806 PrimitiveOrStringType : UNRESTRICTED DOUBLE
michael@0 4807 """
michael@0 4808 p[0] = IDLBuiltinType.Types.unrestricted_double
michael@0 4809
michael@0 4810 def p_PrimitiveOrStringTypeDOMString(self, p):
michael@0 4811 """
michael@0 4812 PrimitiveOrStringType : DOMSTRING
michael@0 4813 """
michael@0 4814 p[0] = IDLBuiltinType.Types.domstring
michael@0 4815
michael@0 4816 def p_PrimitiveOrStringTypeBytestring(self, p):
michael@0 4817 """
michael@0 4818 PrimitiveOrStringType : BYTESTRING
michael@0 4819 """
michael@0 4820 p[0] = IDLBuiltinType.Types.bytestring
michael@0 4821
michael@0 4822 def p_UnsignedIntegerTypeUnsigned(self, p):
michael@0 4823 """
michael@0 4824 UnsignedIntegerType : UNSIGNED IntegerType
michael@0 4825 """
michael@0 4826 p[0] = p[2] + 1 # Adding one to a given signed integer type
michael@0 4827 # gets you the unsigned type.
michael@0 4828
michael@0 4829 def p_UnsignedIntegerType(self, p):
michael@0 4830 """
michael@0 4831 UnsignedIntegerType : IntegerType
michael@0 4832 """
michael@0 4833 p[0] = p[1]
michael@0 4834
michael@0 4835 def p_IntegerTypeShort(self, p):
michael@0 4836 """
michael@0 4837 IntegerType : SHORT
michael@0 4838 """
michael@0 4839 p[0] = IDLBuiltinType.Types.short
michael@0 4840
michael@0 4841 def p_IntegerTypeLong(self, p):
michael@0 4842 """
michael@0 4843 IntegerType : LONG OptionalLong
michael@0 4844 """
michael@0 4845 if p[2]:
michael@0 4846 p[0] = IDLBuiltinType.Types.long_long
michael@0 4847 else:
michael@0 4848 p[0] = IDLBuiltinType.Types.long
michael@0 4849
michael@0 4850 def p_OptionalLong(self, p):
michael@0 4851 """
michael@0 4852 OptionalLong : LONG
michael@0 4853 """
michael@0 4854 p[0] = True
michael@0 4855
michael@0 4856 def p_OptionalLongEmpty(self, p):
michael@0 4857 """
michael@0 4858 OptionalLong :
michael@0 4859 """
michael@0 4860 p[0] = False
michael@0 4861
michael@0 4862 def p_TypeSuffixBrackets(self, p):
michael@0 4863 """
michael@0 4864 TypeSuffix : LBRACKET RBRACKET TypeSuffix
michael@0 4865 """
michael@0 4866 p[0] = [(IDLMethod.TypeSuffixModifier.Brackets, self.getLocation(p, 1))]
michael@0 4867 p[0].extend(p[3])
michael@0 4868
michael@0 4869 def p_TypeSuffixQMark(self, p):
michael@0 4870 """
michael@0 4871 TypeSuffix : QUESTIONMARK TypeSuffixStartingWithArray
michael@0 4872 """
michael@0 4873 p[0] = [(IDLMethod.TypeSuffixModifier.QMark, self.getLocation(p, 1))]
michael@0 4874 p[0].extend(p[2])
michael@0 4875
michael@0 4876 def p_TypeSuffixEmpty(self, p):
michael@0 4877 """
michael@0 4878 TypeSuffix :
michael@0 4879 """
michael@0 4880 p[0] = []
michael@0 4881
michael@0 4882 def p_TypeSuffixStartingWithArray(self, p):
michael@0 4883 """
michael@0 4884 TypeSuffixStartingWithArray : LBRACKET RBRACKET TypeSuffix
michael@0 4885 """
michael@0 4886 p[0] = [(IDLMethod.TypeSuffixModifier.Brackets, self.getLocation(p, 1))]
michael@0 4887 p[0].extend(p[3])
michael@0 4888
michael@0 4889 def p_TypeSuffixStartingWithArrayEmpty(self, p):
michael@0 4890 """
michael@0 4891 TypeSuffixStartingWithArray :
michael@0 4892 """
michael@0 4893 p[0] = []
michael@0 4894
michael@0 4895 def p_Null(self, p):
michael@0 4896 """
michael@0 4897 Null : QUESTIONMARK
michael@0 4898 |
michael@0 4899 """
michael@0 4900 if len(p) > 1:
michael@0 4901 p[0] = True
michael@0 4902 else:
michael@0 4903 p[0] = False
michael@0 4904
michael@0 4905 def p_ReturnTypeType(self, p):
michael@0 4906 """
michael@0 4907 ReturnType : Type
michael@0 4908 """
michael@0 4909 p[0] = p[1]
michael@0 4910
michael@0 4911 def p_ReturnTypeVoid(self, p):
michael@0 4912 """
michael@0 4913 ReturnType : VOID
michael@0 4914 """
michael@0 4915 p[0] = BuiltinTypes[IDLBuiltinType.Types.void]
michael@0 4916
michael@0 4917 def p_ScopedName(self, p):
michael@0 4918 """
michael@0 4919 ScopedName : AbsoluteScopedName
michael@0 4920 | RelativeScopedName
michael@0 4921 """
michael@0 4922 p[0] = p[1]
michael@0 4923
michael@0 4924 def p_AbsoluteScopedName(self, p):
michael@0 4925 """
michael@0 4926 AbsoluteScopedName : SCOPE IDENTIFIER ScopedNameParts
michael@0 4927 """
michael@0 4928 assert False
michael@0 4929 pass
michael@0 4930
michael@0 4931 def p_RelativeScopedName(self, p):
michael@0 4932 """
michael@0 4933 RelativeScopedName : IDENTIFIER ScopedNameParts
michael@0 4934 """
michael@0 4935 assert not p[2] # Not implemented!
michael@0 4936
michael@0 4937 p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1])
michael@0 4938
michael@0 4939 def p_ScopedNameParts(self, p):
michael@0 4940 """
michael@0 4941 ScopedNameParts : SCOPE IDENTIFIER ScopedNameParts
michael@0 4942 """
michael@0 4943 assert False
michael@0 4944 pass
michael@0 4945
michael@0 4946 def p_ScopedNamePartsEmpty(self, p):
michael@0 4947 """
michael@0 4948 ScopedNameParts :
michael@0 4949 """
michael@0 4950 p[0] = None
michael@0 4951
michael@0 4952 def p_ExtendedAttributeNoArgs(self, p):
michael@0 4953 """
michael@0 4954 ExtendedAttributeNoArgs : IDENTIFIER
michael@0 4955 """
michael@0 4956 p[0] = (p[1],)
michael@0 4957
michael@0 4958 def p_ExtendedAttributeArgList(self, p):
michael@0 4959 """
michael@0 4960 ExtendedAttributeArgList : IDENTIFIER LPAREN ArgumentList RPAREN
michael@0 4961 """
michael@0 4962 p[0] = (p[1], p[3])
michael@0 4963
michael@0 4964 def p_ExtendedAttributeIdent(self, p):
michael@0 4965 """
michael@0 4966 ExtendedAttributeIdent : IDENTIFIER EQUALS STRING
michael@0 4967 | IDENTIFIER EQUALS IDENTIFIER
michael@0 4968 """
michael@0 4969 p[0] = (p[1], p[3])
michael@0 4970
michael@0 4971 def p_ExtendedAttributeNamedArgList(self, p):
michael@0 4972 """
michael@0 4973 ExtendedAttributeNamedArgList : IDENTIFIER EQUALS IDENTIFIER LPAREN ArgumentList RPAREN
michael@0 4974 """
michael@0 4975 p[0] = (p[1], p[3], p[5])
michael@0 4976
michael@0 4977 def p_error(self, p):
michael@0 4978 if not p:
michael@0 4979 raise WebIDLError("Syntax Error at end of file. Possibly due to missing semicolon(;), braces(}) or both",
michael@0 4980 [self._filename])
michael@0 4981 else:
michael@0 4982 raise WebIDLError("invalid syntax", [Location(self.lexer, p.lineno, p.lexpos, self._filename)])
michael@0 4983
michael@0 4984 def __init__(self, outputdir='', lexer=None):
michael@0 4985 Tokenizer.__init__(self, outputdir, lexer)
michael@0 4986 self.parser = yacc.yacc(module=self,
michael@0 4987 outputdir=outputdir,
michael@0 4988 tabmodule='webidlyacc',
michael@0 4989 errorlog=yacc.NullLogger(),
michael@0 4990 picklefile='WebIDLGrammar.pkl')
michael@0 4991 self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None)
michael@0 4992 self._installBuiltins(self._globalScope)
michael@0 4993 self._productions = []
michael@0 4994
michael@0 4995 self._filename = "<builtin>"
michael@0 4996 self.lexer.input(Parser._builtins)
michael@0 4997 self._filename = None
michael@0 4998
michael@0 4999 self.parser.parse(lexer=self.lexer,tracking=True)
michael@0 5000
michael@0 5001 def _installBuiltins(self, scope):
michael@0 5002 assert isinstance(scope, IDLScope)
michael@0 5003
michael@0 5004 # xrange omits the last value.
michael@0 5005 for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1):
michael@0 5006 builtin = BuiltinTypes[x]
michael@0 5007 name = builtin.name
michael@0 5008
michael@0 5009 typedef = IDLTypedefType(BuiltinLocation("<builtin type>"), builtin, name)
michael@0 5010 typedef.resolve(scope)
michael@0 5011
michael@0 5012 @ staticmethod
michael@0 5013 def handleModifiers(type, modifiers):
michael@0 5014 for (modifier, modifierLocation) in modifiers:
michael@0 5015 assert modifier == IDLMethod.TypeSuffixModifier.QMark or \
michael@0 5016 modifier == IDLMethod.TypeSuffixModifier.Brackets
michael@0 5017
michael@0 5018 if modifier == IDLMethod.TypeSuffixModifier.QMark:
michael@0 5019 type = IDLNullableType(modifierLocation, type)
michael@0 5020 elif modifier == IDLMethod.TypeSuffixModifier.Brackets:
michael@0 5021 type = IDLArrayType(modifierLocation, type)
michael@0 5022
michael@0 5023 return type
michael@0 5024
michael@0 5025 def parse(self, t, filename=None):
michael@0 5026 self.lexer.input(t)
michael@0 5027
michael@0 5028 #for tok in iter(self.lexer.token, None):
michael@0 5029 # print tok
michael@0 5030
michael@0 5031 self._filename = filename
michael@0 5032 self._productions.extend(self.parser.parse(lexer=self.lexer,tracking=True))
michael@0 5033 self._filename = None
michael@0 5034
michael@0 5035 def finish(self):
michael@0 5036 # First, finish all the IDLImplementsStatements. In particular, we
michael@0 5037 # have to make sure we do those before we do the IDLInterfaces.
michael@0 5038 # XXX khuey hates this bit and wants to nuke it from orbit.
michael@0 5039 implementsStatements = [ p for p in self._productions if
michael@0 5040 isinstance(p, IDLImplementsStatement)]
michael@0 5041 otherStatements = [ p for p in self._productions if
michael@0 5042 not isinstance(p, IDLImplementsStatement)]
michael@0 5043 for production in implementsStatements:
michael@0 5044 production.finish(self.globalScope())
michael@0 5045 for production in otherStatements:
michael@0 5046 production.finish(self.globalScope())
michael@0 5047
michael@0 5048 # Do any post-finish validation we need to do
michael@0 5049 for production in self._productions:
michael@0 5050 production.validate()
michael@0 5051
michael@0 5052 # De-duplicate self._productions, without modifying its order.
michael@0 5053 seen = set()
michael@0 5054 result = []
michael@0 5055 for p in self._productions:
michael@0 5056 if p not in seen:
michael@0 5057 seen.add(p)
michael@0 5058 result.append(p)
michael@0 5059 return result
michael@0 5060
michael@0 5061 def reset(self):
michael@0 5062 return Parser(lexer=self.lexer)
michael@0 5063
michael@0 5064 # Builtin IDL defined by WebIDL
michael@0 5065 _builtins = """
michael@0 5066 typedef unsigned long long DOMTimeStamp;
michael@0 5067 """
michael@0 5068
michael@0 5069 def main():
michael@0 5070 # Parse arguments.
michael@0 5071 from optparse import OptionParser
michael@0 5072 usageString = "usage: %prog [options] files"
michael@0 5073 o = OptionParser(usage=usageString)
michael@0 5074 o.add_option("--cachedir", dest='cachedir', default=None,
michael@0 5075 help="Directory in which to cache lex/parse tables.")
michael@0 5076 o.add_option("--verbose-errors", action='store_true', default=False,
michael@0 5077 help="When an error happens, display the Python traceback.")
michael@0 5078 (options, args) = o.parse_args()
michael@0 5079
michael@0 5080 if len(args) < 1:
michael@0 5081 o.error(usageString)
michael@0 5082
michael@0 5083 fileList = args
michael@0 5084 baseDir = os.getcwd()
michael@0 5085
michael@0 5086 # Parse the WebIDL.
michael@0 5087 parser = Parser(options.cachedir)
michael@0 5088 try:
michael@0 5089 for filename in fileList:
michael@0 5090 fullPath = os.path.normpath(os.path.join(baseDir, filename))
michael@0 5091 f = open(fullPath, 'rb')
michael@0 5092 lines = f.readlines()
michael@0 5093 f.close()
michael@0 5094 print fullPath
michael@0 5095 parser.parse(''.join(lines), fullPath)
michael@0 5096 parser.finish()
michael@0 5097 except WebIDLError, e:
michael@0 5098 if options.verbose_errors:
michael@0 5099 traceback.print_exc()
michael@0 5100 else:
michael@0 5101 print e
michael@0 5102
michael@0 5103 if __name__ == '__main__':
michael@0 5104 main()

mercurial