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