1#!/usr/bin/python3 -i 2# 3# Copyright 2013-2021 The Khronos Group Inc. 4# 5# SPDX-License-Identifier: Apache-2.0 6 7from generator import OutputGenerator, enquote, write 8from scriptgenerator import ScriptOutputGenerator 9 10def nilquote(s): 11 if s: 12 return enquote(s) 13 else: 14 return 'nil' 15 16def makeHash(name): 17 return '@{} = {{'.format(name) 18 19class RubyOutputGenerator(ScriptOutputGenerator): 20 """RubyOutputGenerator - subclass of ScriptOutputGenerator. 21 Generates Ruby data structures describing API names and 22 relationships.""" 23 24 def __init__(self, *args, **kwargs): 25 super().__init__(*args, **kwargs) 26 27 def beginDict(self, name): 28 """String starting definition of a named dictionary""" 29 return f'@{name} = {{' 30 31 def endDict(self): 32 """ String ending definition of a named dictionary""" 33 return '}' 34 35 def writeDict(self, dict, name, printValues = True): 36 """Write dictionary as a Ruby hash with the given name. 37 If printValues is False, just output keys with nil values.""" 38 39 write(self.beginDict(name), file=self.outFile) 40 for key in sorted(dict): 41 if printValues: 42 value = nilquote(dict[key]) 43 else: 44 value = 'nil' 45 write(f'{enquote(key)} => {value},', file=self.outFile) 46 write(self.endDict(), file=self.outFile) 47 48 def writeList(self, l, name): 49 """Write list l as a Ruby hash with the given name""" 50 51 self.writeDict(l, name, printValues = False) 52 53 def makeAccessor(self, name): 54 """Create an accessor method for the hash 'name'""" 55 write('def {}'.format(name), file=self.outFile) 56 write(' @{}'.format(name), file=self.outFile) 57 write('end', file=self.outFile) 58 59 def endFile(self): 60 # Creates the inverse mapping of nonexistent APIs to their aliases. 61 super().createInverseMap() 62 63 # Print out all the dictionaries as Ruby strings. 64 # Use a simple container class for namespace control 65 write('class APInames\n', ' def initialize', file=self.outFile) 66 67 dicts = ( [ self.basetypes, 'basetypes' ], 68 [ self.consts, 'consts' ], 69 [ self.enums, 'enums' ], 70 [ self.flags, 'flags' ], 71 [ self.funcpointers, 'funcpointers' ], 72 [ self.protos, 'protos' ], 73 [ self.structs, 'structs' ], 74 [ self.handles, 'handles' ], 75 [ self.defines, 'defines' ], 76 [ self.typeCategory, 'typeCategory' ], 77 [ self.alias, 'aliases' ], 78 [ self.nonexistent, 'nonexistent' ], 79 ) 80 for (dict, name) in dicts: 81 self.writeDict(dict, name) 82 83 # Dictionary containing the relationships of a type 84 # (e.g. a dictionary with each related type as keys). 85 write(self.beginDict('mapDict'), file=self.outFile) 86 for baseType in sorted(self.mapDict): 87 # Not actually including the relationships yet 88 write('{} => {},'.format(enquote(baseType), 'nil'), 89 file=self.outFile) 90 write(self.endDict(), file=self.outFile) 91 92 # List of included feature names 93 self.writeList(sorted(self.features), 'features') 94 95 # Generate feature <-> interface mappings 96 for feature in self.features: 97 self.mapInterfaces(feature) 98 99 # Write out the reverse map from APIs to requiring features 100 write(self.beginDict('requiredBy'), file=self.outFile) 101 for api in sorted(self.apimap): 102 # Sort requirements by first feature in each one 103 deps = sorted(self.apimap[api], key = lambda dep: dep[0]) 104 reqs = ', '.join('[{}, {}]'.format(nilquote(dep[0]), nilquote(dep[1])) for dep in deps) 105 write('{} => [{}],'.format(enquote(api), reqs), file=self.outFile) 106 write(self.endDict(), file=self.outFile) 107 108 # Remainder of the class definition 109 # End initialize method 110 write('end', file=self.outFile) 111 112 # Accessor methods 113 for (_, name) in dicts: 114 self.makeAccessor(name) 115 self.makeAccessor('features') 116 117 # Class end 118 write('end', file=self.outFile) 119 120 super().endFile() 121