Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Unified Diff: Source/bindings/scripts/idl_definitions.py

Issue 185303013: Remove Perl cruft from IDL compiler front end (mostly JSON export) (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | Source/bindings/scripts/idl_definitions_builder.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/bindings/scripts/idl_definitions.py
diff --git a/Source/bindings/scripts/idl_definitions.py b/Source/bindings/scripts/idl_definitions.py
index 623ca48316dd54ebff82cbda9d694bd17fe51cd8..b0fe3a34f028500fdfacabd0ed694f3ca73b41d8 100644
--- a/Source/bindings/scripts/idl_definitions.py
+++ b/Source/bindings/scripts/idl_definitions.py
@@ -26,41 +26,73 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Blink IDL Intermediate Representation (IR) classes.
+"""Blink IDL Intermediate Representation (IR) classes."""
-Also JSON export, using legacy Perl terms and format, to ensure that both
-parsers produce the same output.
-FIXME: remove BaseIdl, JSON export (json_serializable and to_json), and Perl
-compatibility functions and hacks once Perl compiler gone.
-"""
-
-# Disable attribute hiding check (else JSONEncoder default raises an error)
-# pylint: disable=E0202
# pylint doesn't understand ABCs.
# pylint: disable=W0232, E0203, W0201
import abc
-import json
import re
-# Base classes
+# Type classes
+
+class IdlType(object):
+ # FIXME: replace type strings with these objects,
+ # so don't need to parse everywhere types are used.
+ # Types are stored internally as strings, not objects,
+ # e.g., as 'sequence<Foo>' or 'Foo[]',
+ # hence need to parse the string whenever a type is used.
+ # FIXME: incorporate Nullable, Variadic, etc.
+ # FIXME: properly should nest types
+ # Formally types are nested, e.g., short?[] vs. short[]?,
+ # but in practice these complex types aren't used and can treat
+ # as orthogonal properties.
+ def __init__(self, base_type, is_array=False, is_sequence=False):
+ if is_array and is_sequence:
+ raise ValueError('Array of Sequences are not allowed.')
+ self.base_type = base_type
+ self.is_array = is_array
+ self.is_sequence = is_sequence
+ def __str__(self):
+ type_string = self.base_type
+ if self.is_array:
+ return type_string + '[]'
+ if self.is_sequence:
+ return 'sequence<%s>' % type_string
+ return type_string
-class BaseIdl(object):
- """Abstract base class, used for JSON serialization."""
- __metaclass__ = abc.ABCMeta
+ @classmethod
+ def from_string(cls, type_string):
+ sequence_re = r'^sequence<([^>]*)>$'
+ if type_string.endswith('[]'):
+ type_string = type_string[:-2]
+ sequence_match = re.match(sequence_re, type_string)
+ if sequence_match:
+ raise ValueError('Array of Sequences are not allowed.')
+ return cls(type_string, is_array=True)
+ sequence_match = re.match(sequence_re, type_string)
+ if sequence_match:
+ base_type = sequence_match.group(1)
+ return cls(base_type, is_sequence=True)
+ return cls(type_string)
- @abc.abstractmethod
- def json_serializable(self):
- """Returns a JSON serializable form of the object.
+ def resolve_typedefs(self, typedefs):
+ if self.base_type in typedefs:
+ self.base_type = typedefs[self.base_type]
+ return self # Fluent interface
- This should be a dictionary, with keys scoped names of the form
- Class::key, where the scope is the class name.
- This is so we produce identical output to the Perl code, which uses
- the Perl module JSON.pm, which uses this format.
- """
- pass
+
+class IdlUnionType(object):
+ # FIXME: remove class, just treat as tuple
+ def __init__(self, union_member_types=None):
+ self.union_member_types = union_member_types or []
+
+ def resolve_typedefs(self, typedefs):
+ self.union_member_types = [
+ typedefs.get(union_member_type, union_member_type)
+ for union_member_type in self.union_member_types]
class TypedObject(object):
@@ -90,14 +122,23 @@ class TypedObject(object):
self.idl_type = resolve_typedefs(self.idl_type, typedefs)
+def resolve_typedefs(idl_type, typedefs):
+ """Return an IDL type (as string) with typedefs resolved."""
+ # FIXME: merge into above, as only one use
+ # Converts a string representation to and from an IdlType object to handle
+ # parsing of composite types (arrays and sequences) and encapsulate typedef
+ # resolution, e.g., GLint[] -> unsigned long[] requires parsing the '[]'.
+ # Use fluent interface to avoid auxiliary variable.
+ return str(IdlType.from_string(idl_type).resolve_typedefs(typedefs))
+
+
# IDL classes
-class IdlDefinitions(BaseIdl):
- def __init__(self, callback_functions=None, enumerations=None, file_name=None, interfaces=None, typedefs=None):
+class IdlDefinitions(object):
+ def __init__(self, callback_functions=None, enumerations=None, interfaces=None, typedefs=None):
self.callback_functions = callback_functions or {}
self.enumerations = enumerations or {}
- self.file_name = file_name or None
self.interfaces = interfaces or {}
# Typedefs are not exposed by bindings; resolve typedefs with the
# actual types and then discard the Typedefs.
@@ -111,30 +152,8 @@ class IdlDefinitions(BaseIdl):
for interface in self.interfaces.itervalues():
interface.resolve_typedefs(typedefs)
- def json_serializable(self):
- return {
- 'idlDocument::callbackFunctions': self.callback_functions.values(),
- 'idlDocument::enumerations': self.enumerations.values(),
- 'idlDocument::fileName': self.file_name,
- 'idlDocument::interfaces': sorted(self.interfaces.values()),
- }
-
- def to_json(self, debug=False):
- """Returns a JSON string representing the Definitions.
-
- The JSON output should be identical with the output of the Perl parser,
- specifically the function serializeJSON in idl_serializer.pm,
- which takes a Perl object created by idl_parser.pm.
- """
- # Sort so order consistent, allowing comparison of output
- if debug:
- # indent turns on pretty-printing for legibility
- return json.dumps(self, cls=IdlEncoder, sort_keys=True, indent=4)
- # Use compact separators so output identical to Perl
- return json.dumps(self, cls=IdlEncoder, sort_keys=True, separators=(',', ':'))
-
-
-class IdlCallbackFunction(BaseIdl, TypedObject):
+
+class IdlCallbackFunction(TypedObject):
def __init__(self, name=None, idl_type=None, arguments=None):
self.idl_type = idl_type
self.name = name
@@ -145,27 +164,15 @@ class IdlCallbackFunction(BaseIdl, TypedObject):
for argument in self.arguments:
argument.resolve_typedefs(typedefs)
- def json_serializable(self):
- return {
- 'callbackFunction::name': self.name,
- 'callbackFunction::type': self.idl_type,
- 'callbackFunction::parameters': self.arguments,
- }
-
-class IdlEnum(BaseIdl):
+class IdlEnum(object):
+ # FIXME: remove, just treat enums as a dictionary
def __init__(self, name=None, values=None):
self.name = name
- self.values = values or []
+ self.values = values or [] # FIXME: unnecessary, can't be empty
- def json_serializable(self):
- return {
- 'domEnum::name': self.name,
- 'domEnum::values': self.values,
- }
-
-class IdlInterface(BaseIdl):
+class IdlInterface(object):
def __init__(self, attributes=None, constants=None, constructors=None, custom_constructors=None, extended_attributes=None, operations=None, is_callback=False, is_partial=False, name=None, parent=None):
self.attributes = attributes or []
self.constants = constants or []
@@ -191,21 +198,6 @@ class IdlInterface(BaseIdl):
for operation in self.operations:
operation.resolve_typedefs(typedefs)
- def json_serializable(self):
- return {
- 'domInterface::attributes': self.attributes,
- 'domInterface::constants': self.constants,
- 'domInterface::constructors': self.constructors,
- 'domInterface::customConstructors': self.custom_constructors,
- 'domInterface::extendedAttributes': none_to_value_is_missing(self.extended_attributes),
- 'domInterface::functions': self.operations,
- 'domInterface::isException': false_to_none(self.is_exception),
- 'domInterface::isCallback': boolean_to_perl(false_to_none(self.is_callback)),
- 'domInterface::isPartial': false_to_none(self.is_partial),
- 'domInterface::name': self.name,
- 'domInterface::parent': self.parent,
- }
-
class IdlException(IdlInterface):
# Properly exceptions and interfaces are distinct, and thus should inherit a
@@ -219,7 +211,7 @@ class IdlException(IdlInterface):
self.is_exception = True
-class IdlAttribute(BaseIdl, TypedObject):
+class IdlAttribute(TypedObject):
def __init__(self, idl_type=None, extended_attributes=None, getter_exceptions=None, is_nullable=False, is_static=False, is_read_only=False, name=None, setter_exceptions=None):
self.idl_type = idl_type
self.extended_attributes = extended_attributes or {}
@@ -230,36 +222,16 @@ class IdlAttribute(BaseIdl, TypedObject):
self.name = name
self.setter_exceptions = setter_exceptions or []
- def json_serializable(self):
- return {
- 'domAttribute::extendedAttributes': none_to_value_is_missing(self.extended_attributes),
- 'domAttribute::getterExceptions': self.getter_exceptions,
- 'domAttribute::isNullable': boolean_to_perl_quoted(false_to_none(self.is_nullable)),
- 'domAttribute::isReadOnly': boolean_to_perl(false_to_none(self.is_read_only)),
- 'domAttribute::isStatic': boolean_to_perl(false_to_none(self.is_static)),
- 'domAttribute::name': self.name,
- 'domAttribute::setterExceptions': self.setter_exceptions,
- 'domAttribute::type': self.idl_type,
- }
-
-class IdlConstant(BaseIdl, TypedObject):
+class IdlConstant(TypedObject):
def __init__(self, name=None, idl_type=None, value=None, extended_attributes=None):
self.idl_type = idl_type
self.extended_attributes = extended_attributes or {}
self.name = name
self.value = value
- def json_serializable(self):
- return {
- 'domConstant::extendedAttributes': none_to_value_is_missing(self.extended_attributes),
- 'domConstant::name': self.name,
- 'domConstant::type': self.idl_type,
- 'domConstant::value': self.value,
- }
-
-class IdlOperation(BaseIdl, TypedObject):
+class IdlOperation(TypedObject):
def __init__(self, is_static=False, name=None, idl_type=None, extended_attributes=None, specials=None, arguments=None, overloaded_index=None):
self.is_static = is_static
self.name = name or ''
@@ -267,175 +239,18 @@ class IdlOperation(BaseIdl, TypedObject):
self.extended_attributes = extended_attributes or {}
self.specials = specials or []
self.arguments = arguments or []
- # FIXME: remove overloaded_index (only here for Perl compatibility),
- # as overloading is handled in code generator (v8_interface.py).
- self.overloaded_index = overloaded_index
def resolve_typedefs(self, typedefs):
TypedObject.resolve_typedefs(self, typedefs)
for argument in self.arguments:
argument.resolve_typedefs(typedefs)
- def json_serializable(self):
- return {
- 'domFunction::extendedAttributes': none_to_value_is_missing(self.extended_attributes),
- 'domFunction::isStatic': boolean_to_perl(false_to_none(self.is_static)),
- 'domFunction::name': self.name,
- 'domFunction::overloadedIndex': self.overloaded_index,
- 'domFunction::parameters': self.arguments,
- 'domFunction::specials': self.specials,
- 'domFunction::type': self.idl_type,
- }
-
-class IdlArgument(BaseIdl, TypedObject):
- def __init__(self, name=None, idl_type=None, extended_attributes=None, is_optional=False, is_nullable=None, is_variadic=False):
+class IdlArgument(TypedObject):
+ def __init__(self, name=None, idl_type=None, extended_attributes=None, is_optional=False, is_nullable=False, is_variadic=False):
self.idl_type = idl_type
self.extended_attributes = extended_attributes or {}
- # FIXME: boolean values are inconsistent.
- # The below hack is so that generated JSON is identical to
- # Perl-generated JSON, where the exact values depend on the code path.
- # False and None (Perl: 0 and undef) are semantically interchangeable,
- # but yield different JSON.
- # Once Perl removed, have all default to False.
- if is_optional is None:
- is_optional = False
- if is_variadic is None:
- is_variadic = False
self.is_nullable = is_nullable # (T?)
self.is_optional = is_optional # (optional T)
self.is_variadic = is_variadic # (T...)
self.name = name
-
- def json_serializable(self):
- return {
- 'domParameter::extendedAttributes': none_to_value_is_missing(self.extended_attributes),
- 'domParameter::isNullable': boolean_to_perl_quoted(self.is_nullable),
- 'domParameter::isOptional': boolean_to_perl(self.is_optional),
- 'domParameter::isVariadic': boolean_to_perl(self.is_variadic),
- 'domParameter::name': self.name,
- 'domParameter::type': self.idl_type,
- }
-
-# Type classes
-
-
-def resolve_typedefs(idl_type, typedefs):
- """Return an IDL type (as string) with typedefs resolved."""
- # Converts a string representation to and from an IdlType object to handle
- # parsing of composite types (arrays and sequences) and encapsulate typedef
- # resolution, e.g., GLint[] -> unsigned long[] requires parsing the '[]'.
- # Use fluent interface to avoid auxiliary variable.
- return str(IdlType.from_string(idl_type).resolve_typedefs(typedefs))
-
-
-class IdlType(object):
- # FIXME: replace type strings with these objects,
- # so don't need to parse everywhere types are used.
- # Types are stored internally as strings, not objects,
- # e.g., as 'sequence<Foo>' or 'Foo[]',
- # hence need to parse the string whenever a type is used.
- # FIXME: incorporate Nullable, Variadic, etc.
- # FIXME: properly should nest types
- # Formally types are nested, e.g., short?[] vs. short[]?,
- # but in practice these complex types aren't used and can treat
- # as orthogonal properties.
- def __init__(self, base_type, is_array=False, is_sequence=False):
- if is_array and is_sequence:
- raise ValueError('Array of Sequences are not allowed.')
- self.base_type = base_type
- self.is_array = is_array
- self.is_sequence = is_sequence
-
- def __str__(self):
- type_string = self.base_type
- if self.is_array:
- return type_string + '[]'
- if self.is_sequence:
- return 'sequence<%s>' % type_string
- return type_string
-
- @classmethod
- def from_string(cls, type_string):
- sequence_re = r'^sequence<([^>]*)>$'
- if type_string.endswith('[]'):
- type_string = type_string[:-2]
- sequence_match = re.match(sequence_re, type_string)
- if sequence_match:
- raise ValueError('Array of Sequences are not allowed.')
- return cls(type_string, is_array=True)
- sequence_match = re.match(sequence_re, type_string)
- if sequence_match:
- base_type = sequence_match.group(1)
- return cls(base_type, is_sequence=True)
- return cls(type_string)
-
- def resolve_typedefs(self, typedefs):
- if self.base_type in typedefs:
- self.base_type = typedefs[self.base_type]
- return self # Fluent interface
-
-
-class IdlUnionType(BaseIdl):
- def __init__(self, union_member_types=None):
- self.union_member_types = union_member_types or []
-
- def resolve_typedefs(self, typedefs):
- self.union_member_types = [
- typedefs.get(union_member_type, union_member_type)
- for union_member_type in self.union_member_types]
-
- def json_serializable(self):
- return {
- 'UnionType::unionMemberTypes': self.union_member_types,
- }
-
-
-# Perl JSON compatibility functions
-
-def none_to_value_is_missing(extended_attributes):
- # Perl IDL Parser uses 'VALUE_IS_MISSING' for null values in
- # extended attributes, so add this as a filter when exporting to JSON.
- new_extended_attributes = {}
- for key, value in extended_attributes.iteritems():
- if value is None:
- new_extended_attributes[key] = 'VALUE_IS_MISSING'
- else:
- new_extended_attributes[key] = value
- return new_extended_attributes
-
-
-def boolean_to_perl(value):
- # Perl stores booleans as 1, 0, or undefined (JSON null);
- # convert to this format.
- if value is None:
- return None
- return int(value)
-
-
-def boolean_to_perl_quoted(value):
- # Bug-for-bug compatibility with Perl.
- # The value of isNullable is quoted ('1', '0', or undefined), rather than
- # an integer, so add quotes.
- if value is None:
- return None
- return str(int(value))
-
-
-def false_to_none(value):
- # The Perl parser generally uses undefined (Python None) rather than False
- # for boolean flags, because the value is simply left undefined, rather than
- # explicitly set to False.
- if value is False:
- return None
- return value
-
-
-# JSON export
-
-
-class IdlEncoder(json.JSONEncoder):
- def default(self, obj):
- if isinstance(obj, BaseIdl):
- return obj.json_serializable()
- return json.JSONEncoder.default(self, obj)
« no previous file with comments | « no previous file | Source/bindings/scripts/idl_definitions_builder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698