File: generate_enums.py

package info (click to toggle)
mujoco 2.2.2-3.2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 39,796 kB
  • sloc: ansic: 28,947; cpp: 28,897; cs: 14,241; python: 10,465; xml: 5,104; sh: 93; makefile: 34
file content (126 lines) | stat: -rw-r--r-- 4,109 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# Copyright 2022 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Generates enums.py.

The JSON input can be generated via:
    clang -Xclang -ast-dump=json -fsyntax-only -fparse-all-comments mujoco.h
"""

import json
from typing import Any, Mapping, Sequence

from absl import app
from absl import flags

from google3.third_party.mujoco.introspect import ast_nodes
from google3.third_party.mujoco.introspect.codegen import formatter

FLAGS = flags.FLAGS
flags.DEFINE_string(
    'json_path', None,
    'Path to the JSON file representing the Clang AST for mujoco.h')

ClangJsonNode = Mapping[str, Any]


def traverse(node, visitor):
  visitor.visit(node)
  children = node.get('inner', [])
  for child in children:
    traverse(child, visitor)


class MjEnumVisitor:
  """A Clang AST JSON node visitor for MuJoCo API enum declarations."""

  def __init__(self):
    self._enums = {}
    self._typedefs = {}

  def _make_enum(self, node: ClangJsonNode) -> ast_nodes.EnumDecl:
    """Makes a EnumDecl from a Clang AST EnumDecl node."""
    name = f"enum {node['name']}"
    values = []
    for child in node['inner']:
      child_kind = child.get('kind')
      if child_kind == 'EnumConstantDecl':
        next_idx = values[-1][1] + 1 if values else 0
        value = int(child['inner'][0].get('value', next_idx))
        values.append((child['name'], value))
    return ast_nodes.EnumDecl(name=name, declname=name, values=dict(values))

  def visit(self, node: ClangJsonNode) -> None:
    if (node.get('kind') == 'EnumDecl' and
        node.get('name', '').startswith('mj')):
      enum_decl = self._make_enum(node)
      self._enums[enum_decl.name] = enum_decl
    elif (node.get('kind') == 'TypedefDecl' and
          node['type']['qualType'].startswith('enum mj')):
      enum = self._enums[node['type']['qualType']]
      self._typedefs[node['name']] = ast_nodes.EnumDecl(
          name=node['name'], declname=enum.declname, values=dict(enum.values))

  @property
  def enums(self) -> Mapping[str, ast_nodes.EnumDecl]:
    return self._enums

  @property
  def typedefs(self) -> Mapping[str, ast_nodes.EnumDecl]:
    return self._typedefs


def main(argv: Sequence[str]) -> None:
  if len(argv) > 1:
    raise app.UsageError('Too many command-line arguments.')

  with open(FLAGS.json_path, 'r', encoding='utf-8') as f:
    root = json.load(f)

  visitor = MjEnumVisitor()

  traverse(root, visitor)

  enums_str = formatter.format_as_python_code(visitor.typedefs)

  print(f'''
# Copyright 2022 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Provides information about MuJoCo API enums.

DO NOT EDIT. THIS FILE IS AUTOMATICALLY GENERATED.
"""

from typing import Mapping

from google3.third_party.mujoco.introspect.ast_nodes import EnumDecl

ENUMS: Mapping[str, EnumDecl] = {enums_str}
'''.strip())  # `print` adds a trailing newline


if __name__ == '__main__':
  app.run(main)