diff options
author | Jon Leech <[email protected]> | 2019-08-17 15:58:46 -0700 |
---|---|---|
committer | Jon Leech <[email protected]> | 2019-08-17 15:59:53 -0700 |
commit | 4ee33d2fbd1e7a072c4d8a6cf8f01c4f96d7483d (patch) | |
tree | 267945d47d5ce0a4ccff68e1a6523aad4f766f5a /registry/conventions.py | |
parent | 23b2e8e64bdf3f25b3d73f1593e72977ebfcd39b (diff) | |
download | Vulkan-Headers-4ee33d2fbd1e7a072c4d8a6cf8f01c4f96d7483d.tar.gz Vulkan-Headers-4ee33d2fbd1e7a072c4d8a6cf8f01c4f96d7483d.zip |
Update for Vulkan-Docs 1.1.120v1.1.120
Diffstat (limited to 'registry/conventions.py')
-rw-r--r-- | registry/conventions.py | 254 |
1 files changed, 219 insertions, 35 deletions
diff --git a/registry/conventions.py b/registry/conventions.py index b37a494..8991b17 100644 --- a/registry/conventions.py +++ b/registry/conventions.py @@ -17,35 +17,96 @@ # Base class for working-group-specific style conventions, # used in generation. -from abc import ABCMeta, abstractmethod +from enum import Enum -ABC = ABCMeta('ABC', (object,), {}) +# Type categories that respond "False" to isStructAlwaysValid +# basetype is home to typedefs like ..Bool32 +CATEGORIES_REQUIRING_VALIDATION = set(('handle', + 'enum', + 'bitmask', + 'basetype', + None)) -class ConventionsBase(ABC): +# These are basic C types pulled in via openxr_platform_defines.h +TYPES_KNOWN_ALWAYS_VALID = set(('char', + 'float', + 'int8_t', 'uint8_t', + 'int32_t', 'uint32_t', + 'int64_t', 'uint64_t', + 'size_t', + 'uintptr_t', + 'int', + )) + + +class ProseListFormats(Enum): + """A connective, possibly with a quantifier.""" + AND = 0 + EACH_AND = 1 + OR = 2 + ANY_OR = 3 + + @classmethod + def from_string(cls, s): + if s == 'or': + return cls.OR + if s == 'and': + return cls.AND + return None + + @property + def connective(self): + if self in (ProseListFormats.OR, ProseListFormats.ANY_OR): + return 'or' + return 'and' + + def quantifier(self, n): + """Return the desired quantifier for a list of a given length.""" + if self == ProseListFormats.ANY_OR: + if n > 1: + return 'any of ' + elif self == ProseListFormats.EACH_AND: + if n > 2: + return 'each of ' + if n == 2: + return 'both of ' + return '' + + +class ConventionsBase: """WG-specific conventions.""" - @abstractmethod + def __init__(self): + self._command_prefix = None + self._type_prefix = None + def formatExtension(self, name): - """Mark up a name as an extension for the spec.""" + """Mark up a name as an extension for the spec. + + Must implement.""" raise NotImplementedError @property - @abstractmethod def null(self): """Preferred spelling of NULL.""" raise NotImplementedError - def makeProseList(self, elements, connective='and'): + def makeProseList(self, elements, fmt=ProseListFormats.AND, with_verb=False, *args, **kwargs): """Make a (comma-separated) list for use in prose. Adds a connective (by default, 'and') before the last element if there are more than 1. + Adds the right one of "is" or "are" to the end if with_verb is true. + + Optionally adds a quantifier (like 'any') before a list of 2 or more, + if specified by fmt. + Override with a different method or different call to _implMakeProseList if you want to add a comma for two elements, or not use a serial comma. """ - return self._implMakeProseList(elements, connective) + return self._implMakeProseList(elements, fmt, with_verb, *args, **kwargs) @property def struct_macro(self): @@ -55,20 +116,20 @@ class ConventionsBase(ABC): """ return 'sname:' - def makeStructName(self, name): - """Prepend the appropriate format macro for a structure to a structure type name. - - Uses struct_macro, so just override that if you want to change behavior. - """ - return self.struct_macro + name - @property def external_macro(self): """Get the appropriate format macro for an external type like uint32_t. May override. """ - return 'basetype:' + return 'code:' + + def makeStructName(self, name): + """Prepend the appropriate format macro for a structure to a structure type name. + + Uses struct_macro, so just override that if you want to change behavior. + """ + return self.struct_macro + name def makeExternalTypeName(self, name): """Prepend the appropriate format macro for an external type like uint32_t to a type name. @@ -77,7 +138,7 @@ class ConventionsBase(ABC): """ return self.external_macro + name - def _implMakeProseList(self, elements, connective, comma_for_two_elts=False, serial_comma=True): + def _implMakeProseList(self, elements, fmt, with_verb, comma_for_two_elts=False, serial_comma=True): """Internal-use implementation to make a (comma-separated) list for use in prose. Adds a connective (by default, 'and') @@ -85,48 +146,171 @@ class ConventionsBase(ABC): and only includes commas if there are more than 2 (if comma_for_two_elts is False). + Adds the right one of "is" or "are" to the end if with_verb is true. + + Optionally adds a quantifier (like 'any') before a list of 2 or more, + if specified by fmt. + Don't edit these defaults, override self.makeProseList(). """ assert(serial_comma) # didn't implement what we didn't need + if isinstance(fmt, str): + fmt = ProseListFormats.from_string(fmt) + my_elts = list(elements) if len(my_elts) > 1: - my_elts[-1] = '{} {}'.format(connective, my_elts[-1]) + my_elts[-1] = '{} {}'.format(fmt.connective, my_elts[-1]) if not comma_for_two_elts and len(my_elts) <= 2: - return ' '.join(my_elts) - return ', '.join(my_elts) + prose = ' '.join(my_elts) + else: + prose = ', '.join(my_elts) + + quantifier = fmt.quantifier(len(my_elts)) + + parts = [quantifier, prose] + + if with_verb: + if len(my_elts) > 1: + parts.append(' are') + else: + parts.append(' is') + return ''.join(parts) @property - @abstractmethod def file_suffix(self): """Return suffix of generated Asciidoctor files""" raise NotImplementedError - @abstractmethod - def api_name(self, spectype = None): - """Return API name""" + def api_name(self, spectype=None): + """Return API or specification name for citations in ref pages. + + spectype is the spec this refpage is for. + 'api' (the default value) is the main API Specification. + If an unrecognized spectype is given, returns None. + + Must implement.""" raise NotImplementedError + def should_insert_may_alias_macro(self, genOpts): + """Return true if we should insert a "may alias" macro in this file. + + Only used by OpenXR right now.""" + return False + + @property + def command_prefix(self): + """Return the expected prefix of commands/functions. + + Implemented in terms of api_prefix.""" + if not self._command_prefix: + self._command_prefix = self.api_prefix[:].replace('_', '').lower() + return self._command_prefix + + @property + def type_prefix(self): + """Return the expected prefix of type names. + + Implemented in terms of command_prefix (and in turn, api_prefix).""" + if not self._type_prefix: + self._type_prefix = ''.join( + (self.command_prefix[0:1].upper(), self.command_prefix[1:])) + return self._type_prefix + @property - @abstractmethod def api_prefix(self): - """Return API token prefix""" + """Return API token prefix. + + Typically two uppercase letters followed by an underscore. + + Must implement.""" raise NotImplementedError @property - @abstractmethod def api_version_prefix(self): - """Return API core version token prefix""" - raise NotImplementedError + """Return API core version token prefix. + + Implemented in terms of api_prefix. + + May override.""" + return self.api_prefix + 'VERSION_' @property - @abstractmethod def KHR_prefix(self): - """Return extension name prefix for KHR extensions""" - raise NotImplementedError + """Return extension name prefix for KHR extensions. + + Implemented in terms of api_prefix. + + May override.""" + return self.api_prefix + 'KHR_' @property - @abstractmethod def EXT_prefix(self): - """Return extension name prefix for EXT extensions""" - raise NotImplementedError + """Return extension name prefix for EXT extensions. + + Implemented in terms of api_prefix. + + May override.""" + return self.api_prefix + 'EXT_' + + def writeFeature(self, featureExtraProtect, filename): + """Return True if OutputGenerator.endFeature should write this feature. + + Defaults to always True. + Used in COutputGenerator. + + May override.""" + return True + + def requires_error_validation(self, return_type): + """Return True if the return_type element is an API result code + requiring error validation. + + Defaults to always False. + + May override.""" + return False + + @property + def required_errors(self): + """Return a list of required error codes for validation. + + Defaults to an empty list. + + May override.""" + return [] + + def is_voidpointer_alias(self, tag, text, tail): + """Return True if the declaration components (tag,text,tail) of an + element represents a void * type. + + Defaults to a reasonable implementation. + + May override.""" + return tag == 'type' and text == 'void' and tail.startswith('*') + + def make_voidpointer_alias(self, tail): + """Reformat a void * declaration to include the API alias macro. + + Defaults to a no-op. + + Must override if you actually want to use this feature in your project.""" + return tail + + def category_requires_validation(self, category): + """Return True if the given type 'category' always requires validation. + + Defaults to a reasonable implementation. + + May override.""" + return category in CATEGORIES_REQUIRING_VALIDATION + + def type_always_valid(self, typename): + """Return True if the given type name is always valid (never requires validation). + + This is for things like integers. + + Defaults to a reasonable implementation. + + May override.""" + return typename in TYPES_KNOWN_ALWAYS_VALID |