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