• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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