| #!/usr/bin/env python3 | |
| # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
| # for details. All rights reserved. Use of this source code is governed by a | |
| # BSD-style license that can be found in the LICENSE file. | |
| from idlnode import * | |
| def render(idl_node, indent_str=' '): | |
| output = [] | |
| indent_stack = [] | |
| def begin_indent(): | |
| indent_stack.append(indent_str) | |
| def end_indent(): | |
| indent_stack.pop() | |
| def sort(nodes): | |
| return sorted(nodes, key=lambda node: node.id) | |
| def wln(node=None): | |
| """Writes the given node and adds a new line.""" | |
| w(node) | |
| output.append('\n') | |
| def wsp(node): | |
| """Writes the given node and adds a space if there was output.""" | |
| mark = len(output) | |
| w(node) | |
| if mark != len(output): | |
| w(' ') | |
| def w(node, list_separator=None): | |
| """Writes the given node. | |
| Args: | |
| node -- a string, IDLNode instance or a list of such. | |
| list_separator -- if provided, and node is a list, | |
| list_separator will be written between the list items. | |
| """ | |
| if node is None: | |
| return | |
| elif isinstance(node, str): | |
| if output and output[-1].endswith('\n'): | |
| # Auto-indent. | |
| output.extend(indent_stack) | |
| output.append(node) | |
| elif isinstance(node, list): | |
| for i in range(0, len(node)): | |
| if i > 0: | |
| w(list_separator) | |
| w(node[i]) | |
| elif isinstance(node, IDLFile): | |
| w(node.interfaces) | |
| w(node.enums) | |
| w(node.typeDefs) | |
| elif isinstance(node, IDLModule): | |
| wsp(node.annotations) | |
| wsp(node.ext_attrs) | |
| wln('module %s {' % node.id) | |
| begin_indent() | |
| w(node.interfaces) | |
| w(node.enums) | |
| w(node.typeDefs) | |
| end_indent() | |
| wln('};') | |
| elif isinstance(node, IDLEnum): | |
| w('enum %s {}' % node.id) | |
| # TODO(antonm): emit values as well. | |
| elif isinstance(node, IDLInterface): | |
| if node.annotations: | |
| wln(node.annotations) | |
| if node.ext_attrs: | |
| wln(node.ext_attrs) | |
| w('interface %s' % node.id) | |
| begin_indent() | |
| begin_indent() | |
| if node.parents: | |
| wln(' :') | |
| w(node.parents, ',\n') | |
| wln(' {') | |
| end_indent() | |
| if node.constants: | |
| wln() | |
| wln('/* Constants */') | |
| w(sort(node.constants)) | |
| if node.attributes: | |
| wln() | |
| wln('/* Attributes */') | |
| w(sort(node.attributes)) | |
| if node.operations: | |
| wln() | |
| wln('/* Operations */') | |
| w(sort(node.operations)) | |
| end_indent() | |
| wln('};') | |
| elif isinstance(node, IDLParentInterface): | |
| wsp(node.annotations) | |
| w(node.type.id) | |
| elif isinstance(node, IDLAnnotations): | |
| sep = '' | |
| for (name, annotation) in sorted(node.items()): | |
| w(sep) | |
| sep = ' ' | |
| if annotation and len(annotation): | |
| subRes = [] | |
| for (argName, argValue) in sorted(annotation.items()): | |
| if argValue is None: | |
| subRes.append(argName) | |
| else: | |
| subRes.append('%s=%s' % (argName, argValue)) | |
| w('@%s(%s)' % (name, ', '.join(subRes))) | |
| else: | |
| w('@%s' % name) | |
| elif isinstance(node, IDLExtAttrs): | |
| if len(node): | |
| w('[') | |
| i = 0 | |
| for k in sorted(node): | |
| if i > 0: | |
| w(', ') | |
| w(k) | |
| v = node[k] | |
| if v is not None: | |
| if isinstance(v, IDLExtAttrFunctionValue): | |
| if v.id: | |
| w('=') | |
| w(v) | |
| elif isinstance(v, list): | |
| assert k == 'Constructor' | |
| w(v[0]) | |
| for c in v[1:]: | |
| w(', ') | |
| w(k) | |
| w(c) | |
| else: | |
| w('=%s' % v.__str__()) | |
| i += 1 | |
| w(']') | |
| elif isinstance(node, IDLExtAttrFunctionValue): | |
| if node.id: | |
| w(node.id) | |
| w('(') | |
| w(node.arguments, ', ') | |
| w(')') | |
| elif isinstance(node, IDLAttribute): | |
| wsp(node.annotations) | |
| wsp(node.ext_attrs) | |
| if node.is_read_only: | |
| w('readonly ') | |
| w('attribute ') | |
| w(node.type.id) | |
| if (node.type.nullable): | |
| w('?') | |
| w(' ') | |
| w(node.id) | |
| wln(';') | |
| elif isinstance(node, IDLConstant): | |
| wsp(node.annotations) | |
| wsp(node.ext_attrs) | |
| wln('const %s %s = %s;' % (node.type.id, node.id, node.value)) | |
| elif isinstance(node, IDLOperation): | |
| wsp(node.annotations) | |
| wsp(node.ext_attrs) | |
| if node.is_static: | |
| w('static ') | |
| if node.specials: | |
| w(node.specials, ' ') | |
| w(' ') | |
| w(node.type.id) | |
| if (node.type.nullable): | |
| w('?') | |
| w(' ') | |
| w(node.id) | |
| w('(') | |
| w(node.arguments, ', ') | |
| w(')') | |
| wln(';') | |
| elif isinstance(node, IDLArgument): | |
| wsp(node.ext_attrs) | |
| if (node.optional): | |
| w('optional ') | |
| w(node.type.id) | |
| if node.type.nullable: | |
| w('?') | |
| w(' %s' % node.id) | |
| else: | |
| raise TypeError("Expected str or IDLNode but %s found" % type(node)) | |
| w(idl_node) | |
| return ''.join(output) |