diff options
Diffstat (limited to 'codegen/vulkan/scripts/rubygenerator.py')
-rw-r--r-- | codegen/vulkan/scripts/rubygenerator.py | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/codegen/vulkan/scripts/rubygenerator.py b/codegen/vulkan/scripts/rubygenerator.py new file mode 100644 index 00000000..8042d9b8 --- /dev/null +++ b/codegen/vulkan/scripts/rubygenerator.py @@ -0,0 +1,120 @@ +#!/usr/bin/python3 -i +# +# Copyright 2013-2021 The Khronos Group Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +from generator import OutputGenerator, enquote, write +from scriptgenerator import ScriptOutputGenerator + +def nilquote(s): + if s: + return enquote(s) + else: + return 'nil' + +def makeHash(name): + return '@{} = {{'.format(name) + +class RubyOutputGenerator(ScriptOutputGenerator): + """RubyOutputGenerator - subclass of ScriptOutputGenerator. + Generates Ruby data structures describing API names and + relationships.""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def beginDict(self, name): + """String starting definition of a named dictionary""" + return f'@{name} = {{' + + def endDict(self): + """ String ending definition of a named dictionary""" + return '}' + + def writeDict(self, dict, name, printValues = True): + """Write dictionary as a Ruby hash with the given name. + If printValues is False, just output keys with nil values.""" + + write(self.beginDict(name), file=self.outFile) + for key in sorted(dict): + if printValues: + value = nilquote(dict[key]) + else: + value = 'nil' + write(f'{enquote(key)} => {value},', file=self.outFile) + write(self.endDict(), file=self.outFile) + + def writeList(self, l, name): + """Write list l as a Ruby hash with the given name""" + + self.writeDict(l, name, printValues = False) + + def makeAccessor(self, name): + """Create an accessor method for the hash 'name'""" + write('def {}'.format(name), file=self.outFile) + write(' @{}'.format(name), file=self.outFile) + write('end', file=self.outFile) + + def endFile(self): + # Creates the inverse mapping of nonexistent APIs to their aliases. + super().createInverseMap() + + # Print out all the dictionaries as Ruby strings. + # Use a simple container class for namespace control + write('class APInames\n', ' def initialize', file=self.outFile) + + dicts = ( [ self.basetypes, 'basetypes' ], + [ self.consts, 'consts' ], + [ self.enums, 'enums' ], + [ self.flags, 'flags' ], + [ self.funcpointers, 'funcpointers' ], + [ self.protos, 'protos' ], + [ self.structs, 'structs' ], + [ self.handles, 'handles' ], + [ self.defines, 'defines' ], + [ self.typeCategory, 'typeCategory' ], + [ self.alias, 'aliases' ], + [ self.nonexistent, 'nonexistent' ], + ) + for (dict, name) in dicts: + self.writeDict(dict, name) + + # Dictionary containing the relationships of a type + # (e.g. a dictionary with each related type as keys). + write(self.beginDict('mapDict'), file=self.outFile) + for baseType in sorted(self.mapDict): + # Not actually including the relationships yet + write('{} => {},'.format(enquote(baseType), 'nil'), + file=self.outFile) + write(self.endDict(), file=self.outFile) + + # List of included feature names + self.writeList(sorted(self.features), 'features') + + # Generate feature <-> interface mappings + for feature in self.features: + self.mapInterfaces(feature) + + # Write out the reverse map from APIs to requiring features + write(self.beginDict('requiredBy'), file=self.outFile) + for api in sorted(self.apimap): + # Sort requirements by first feature in each one + deps = sorted(self.apimap[api], key = lambda dep: dep[0]) + reqs = ', '.join('[{}, {}]'.format(nilquote(dep[0]), nilquote(dep[1])) for dep in deps) + write('{} => [{}],'.format(enquote(api), reqs), file=self.outFile) + write(self.endDict(), file=self.outFile) + + # Remainder of the class definition + # End initialize method + write('end', file=self.outFile) + + # Accessor methods + for (_, name) in dicts: + self.makeAccessor(name) + self.makeAccessor('features') + + # Class end + write('end', file=self.outFile) + + super().endFile() |