Commit 980a58e4 authored by Ken Rockot's avatar Ken Rockot Committed by Commit Bot

Apply Python formatting to mojom library

This is strictly a formatting change, generated by manually running yapf
over the affected files. It's a precursor to a subsequent move and minor
refactoring of this code, as modified files will always get yapf applied
and that would otherwise create a lot of noise in the coming CLs.

Bug: 1060467
Change-Id: I188ac6cc71fda2cd08a6f4695f67c5c0f04d2737
Tbr: oksamyt@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2098265Reviewed-by: default avatarKen Rockot <rockot@google.com>
Commit-Queue: Ken Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#749272}
parent 515438bc
......@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
class Error(Exception):
"""Base class for Mojo IDL bindings parser/generator errors."""
......
......@@ -5,6 +5,7 @@
import errno
import os.path
def EnsureDirectoryExists(path, always_try_to_create=False):
"""A wrapper for os.makedirs that does not error if the directory already
exists. A different process could be racing to create this directory."""
......
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Resolves the values used for constants and enums."""
from itertools import ifilter
import mojom.generate.module as mojom
def ResolveConstants(module, expression_to_text):
in_progress = set()
computed = set()
......@@ -14,8 +14,9 @@ def ResolveConstants(module, expression_to_text):
def GetResolvedValue(named_value):
assert isinstance(named_value, (mojom.EnumValue, mojom.ConstantValue))
if isinstance(named_value, mojom.EnumValue):
field = next(ifilter(lambda field: field.name == named_value.name,
named_value.enum.fields), None)
field = next(
ifilter(lambda field: field.name == named_value.name,
named_value.enum.fields), None)
if not field:
raise RuntimeError(
'Unable to get computed value for field %s of enum %s' %
......
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Code shared by the various language-specific code generators."""
from __future__ import print_function
......@@ -35,6 +34,7 @@ def SplitCamelCase(identifier):
identifier = re.sub('([a-z][0-9]*)(?=[A-Z])', r'\1_', identifier)
return [x.lower() for x in identifier.split('_')]
def ToCamel(identifier, lower_initial=False, dilimiter='_'):
"""Splits |identifier| using |dilimiter|, makes the first character of each
word uppercased (but makes the first character of the first word lowercased
......@@ -42,11 +42,12 @@ def ToCamel(identifier, lower_initial=False, dilimiter='_'):
each word, all the characters except the first one are untouched.
"""
result = ''.join(word[0].upper() + word[1:]
for word in identifier.split(dilimiter) if word)
for word in identifier.split(dilimiter) if word)
if lower_initial and result:
result = result[0].lower() + result[1:]
return result
def ToConstantCase(identifier):
"""Splits camel-cased |identifier| into lower case words, removes the first
word if it's "k" and joins them using "_" e.g. for "URLLoaderFactory", returns
......@@ -62,6 +63,7 @@ def ToConstantCase(identifier):
return '_'.join([word.upper() for word in words])
class Stylizer(object):
"""Stylizers specify naming rules to map mojom names to names in generated
code. For example, if you would like method_name in mojom to be mapped to
......@@ -167,8 +169,11 @@ def AddComputedData(module):
method.mojom_name)
struct = mojom.Struct(params_class, module=method.interface.module)
for param in method.parameters:
struct.AddField(param.mojom_name, param.kind, param.ordinal,
attributes=param.attributes)
struct.AddField(
param.mojom_name,
param.kind,
param.ordinal,
attributes=param.attributes)
_AddStructComputedData(False, struct)
return struct
......@@ -178,8 +183,11 @@ def AddComputedData(module):
method.mojom_name)
struct = mojom.Struct(params_class, module=method.interface.module)
for param in method.response_parameters:
struct.AddField(param.mojom_name, param.kind, param.ordinal,
attributes=param.attributes)
struct.AddField(
param.mojom_name,
param.kind,
param.ordinal,
attributes=param.attributes)
_AddStructComputedData(False, struct)
return struct
......@@ -194,15 +202,24 @@ def AddComputedData(module):
class Generator(object):
# Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all
# files to stdout.
def __init__(self, module, output_dir=None, typemap=None, variant=None,
bytecode_path=None, for_blink=False,
def __init__(self,
module,
output_dir=None,
typemap=None,
variant=None,
bytecode_path=None,
for_blink=False,
js_bindings_mode="new",
js_generate_struct_deserializers=False,
export_attribute=None,
export_header=None, generate_non_variant_code=False,
support_lazy_serialization=False, disallow_native_types=False,
disallow_interfaces=False, generate_message_ids=False,
generate_fuzzing=False, enable_kythe_annotations=False,
export_header=None,
generate_non_variant_code=False,
support_lazy_serialization=False,
disallow_native_types=False,
disallow_interfaces=False,
generate_message_ids=False,
generate_fuzzing=False,
enable_kythe_annotations=False,
extra_cpp_template_paths=None):
self.module = module
self.output_dir = output_dir
......
......@@ -12,6 +12,7 @@
# method = interface.AddMethod('Tat', 0)
# method.AddParameter('baz', 0, mojom.INT32)
# We use our own version of __repr__ when displaying the AST, as the
# AST currently doesn't capture which nodes are reference (e.g. to
# types) and which nodes are definitions. This allows us to e.g. print
......@@ -40,15 +41,16 @@ def Repr(obj, as_ref=True):
if not obj:
return '[]'
else:
return ('[\n%s\n]' % (',\n'.join(' %s' % Repr(elem, as_ref).replace(
'\n', '\n ') for elem in obj)))
return ('[\n%s\n]' % (',\n'.join(
' %s' % Repr(elem, as_ref).replace('\n', '\n ')
for elem in obj)))
elif isinstance(obj, dict):
if not obj:
return '{}'
else:
return ('{\n%s\n}' % (',\n'.join(' %s: %s' % (
Repr(key, as_ref).replace('\n', '\n '),
Repr(val, as_ref).replace('\n', '\n '))
return ('{\n%s\n}' % (',\n'.join(
' %s: %s' % (Repr(key, as_ref).replace('\n', '\n '),
Repr(val, as_ref).replace('\n', '\n '))
for key, val in obj.items())))
else:
return repr(obj)
......@@ -66,6 +68,7 @@ def GenericRepr(obj, names):
Returns:
A str representation of |obj|.
"""
def ReprIndent(name, as_ref):
return ' %s=%s' % (name, Repr(getattr(obj, name), as_ref).replace(
'\n', '\n '))
......@@ -83,6 +86,7 @@ class Kind(object):
parent_kind: The enclosing type. For example, an enum defined
inside an interface has that interface as its parent. May be None.
"""
def __init__(self, spec=None, module=None):
self.spec = spec
self.module = module
......@@ -105,6 +109,7 @@ class ReferenceKind(Kind):
Attributes:
is_nullable: True if the type is nullable.
"""
def __init__(self, spec=None, is_nullable=False, module=None):
assert spec is None or is_nullable == spec.startswith('?')
Kind.__init__(self, spec, module)
......@@ -155,6 +160,7 @@ class ReferenceKind(Kind):
a.name = 'test_struct_2'
print(b.name) # Outputs 'test_struct_2'.
"""
def Get(self):
try:
return self.shared_definition[name]
......@@ -168,63 +174,61 @@ class ReferenceKind(Kind):
# Initialize the set of primitive types. These can be accessed by clients.
BOOL = Kind('b')
INT8 = Kind('i8')
INT16 = Kind('i16')
INT32 = Kind('i32')
INT64 = Kind('i64')
UINT8 = Kind('u8')
UINT16 = Kind('u16')
UINT32 = Kind('u32')
UINT64 = Kind('u64')
FLOAT = Kind('f')
DOUBLE = Kind('d')
STRING = ReferenceKind('s')
HANDLE = ReferenceKind('h')
DCPIPE = ReferenceKind('h:d:c')
DPPIPE = ReferenceKind('h:d:p')
MSGPIPE = ReferenceKind('h:m')
SHAREDBUFFER = ReferenceKind('h:s')
PLATFORMHANDLE = ReferenceKind('h:p')
NULLABLE_STRING = ReferenceKind('?s', True)
NULLABLE_HANDLE = ReferenceKind('?h', True)
NULLABLE_DCPIPE = ReferenceKind('?h:d:c', True)
NULLABLE_DPPIPE = ReferenceKind('?h:d:p', True)
NULLABLE_MSGPIPE = ReferenceKind('?h:m', True)
BOOL = Kind('b')
INT8 = Kind('i8')
INT16 = Kind('i16')
INT32 = Kind('i32')
INT64 = Kind('i64')
UINT8 = Kind('u8')
UINT16 = Kind('u16')
UINT32 = Kind('u32')
UINT64 = Kind('u64')
FLOAT = Kind('f')
DOUBLE = Kind('d')
STRING = ReferenceKind('s')
HANDLE = ReferenceKind('h')
DCPIPE = ReferenceKind('h:d:c')
DPPIPE = ReferenceKind('h:d:p')
MSGPIPE = ReferenceKind('h:m')
SHAREDBUFFER = ReferenceKind('h:s')
PLATFORMHANDLE = ReferenceKind('h:p')
NULLABLE_STRING = ReferenceKind('?s', True)
NULLABLE_HANDLE = ReferenceKind('?h', True)
NULLABLE_DCPIPE = ReferenceKind('?h:d:c', True)
NULLABLE_DPPIPE = ReferenceKind('?h:d:p', True)
NULLABLE_MSGPIPE = ReferenceKind('?h:m', True)
NULLABLE_SHAREDBUFFER = ReferenceKind('?h:s', True)
NULLABLE_PLATFORMHANDLE = ReferenceKind('?h:p', True)
# Collection of all Primitive types
PRIMITIVES = (
BOOL,
INT8,
INT16,
INT32,
INT64,
UINT8,
UINT16,
UINT32,
UINT64,
FLOAT,
DOUBLE,
STRING,
HANDLE,
DCPIPE,
DPPIPE,
MSGPIPE,
SHAREDBUFFER,
PLATFORMHANDLE,
NULLABLE_STRING,
NULLABLE_HANDLE,
NULLABLE_DCPIPE,
NULLABLE_DPPIPE,
NULLABLE_MSGPIPE,
NULLABLE_SHAREDBUFFER,
NULLABLE_PLATFORMHANDLE,
BOOL,
INT8,
INT16,
INT32,
INT64,
UINT8,
UINT16,
UINT32,
UINT64,
FLOAT,
DOUBLE,
STRING,
HANDLE,
DCPIPE,
DPPIPE,
MSGPIPE,
SHAREDBUFFER,
PLATFORMHANDLE,
NULLABLE_STRING,
NULLABLE_HANDLE,
NULLABLE_DCPIPE,
NULLABLE_DPPIPE,
NULLABLE_MSGPIPE,
NULLABLE_SHAREDBUFFER,
NULLABLE_PLATFORMHANDLE,
)
ATTRIBUTE_MIN_VERSION = 'MinVersion'
ATTRIBUTE_EXTENSIBLE = 'Extensible'
ATTRIBUTE_SYNC = 'Sync'
......@@ -238,8 +242,8 @@ class NamedValue(object):
def GetSpec(self):
return (self.module.mojom_namespace + '.' +
(self.parent_kind and (self.parent_kind.mojom_name + '.') or "") +
self.mojom_name)
(self.parent_kind and
(self.parent_kind.mojom_name + '.') or "") + self.mojom_name)
class BuiltinValue(object):
......@@ -265,8 +269,8 @@ class EnumValue(NamedValue):
def GetSpec(self):
return (self.module.mojom_namespace + '.' +
(self.parent_kind and (self.parent_kind.mojom_name + '.') or "") +
self.enum.mojom_name + '.' + self.mojom_name)
(self.parent_kind and (self.parent_kind.mojom_name + '.')
or "") + self.enum.mojom_name + '.' + self.mojom_name)
@property
def name(self):
......@@ -285,7 +289,11 @@ class Constant(object):
class Field(object):
def __init__(self, mojom_name=None, kind=None, ordinal=None, default=None,
def __init__(self,
mojom_name=None,
kind=None,
ordinal=None,
default=None,
attributes=None):
if self.__class__.__name__ == 'Field':
raise Exception()
......@@ -309,10 +317,12 @@ class Field(object):
if self.attributes else None
class StructField(Field): pass
class StructField(Field):
pass
class UnionField(Field): pass
class UnionField(Field):
pass
class Struct(ReferenceKind):
......@@ -357,14 +367,21 @@ class Struct(ReferenceKind):
def Repr(self, as_ref=True):
if as_ref:
return '<%s mojom_name=%r module=%s>' % (
self.__class__.__name__, self.mojom_name,
Repr(self.module, as_ref=True))
return '<%s mojom_name=%r module=%s>' % (self.__class__.__name__,
self.mojom_name,
Repr(self.module, as_ref=True))
else:
return GenericRepr(self,
{'mojom_name': False, 'fields': False, 'module': True})
def AddField(self, mojom_name, kind, ordinal=None, default=None,
return GenericRepr(self, {
'mojom_name': False,
'fields': False,
'module': True
})
def AddField(self,
mojom_name,
kind,
ordinal=None,
default=None,
attributes=None):
field = StructField(mojom_name, kind, ordinal, default, attributes)
self.fields.append(field)
......@@ -409,8 +426,8 @@ class Union(ReferenceKind):
def Repr(self, as_ref=True):
if as_ref:
return '<%s spec=%r is_nullable=%r fields=%s>' % (
self.__class__.__name__, self.spec, self.is_nullable,
Repr(self.fields))
self.__class__.__name__, self.spec, self.is_nullable, Repr(
self.fields))
else:
return GenericRepr(self, {'fields': True, 'is_nullable': False})
......@@ -452,11 +469,14 @@ class Array(ReferenceKind):
def Repr(self, as_ref=True):
if as_ref:
return '<%s spec=%r is_nullable=%r kind=%s length=%r>' % (
self.__class__.__name__, self.spec, self.is_nullable, Repr(self.kind),
self.length)
self.__class__.__name__, self.spec, self.is_nullable, Repr(
self.kind), self.length)
else:
return GenericRepr(self, {'kind': True, 'length': False,
'is_nullable': False})
return GenericRepr(self, {
'kind': True,
'length': False,
'is_nullable': False
})
class Map(ReferenceKind):
......@@ -471,9 +491,8 @@ class Map(ReferenceKind):
def __init__(self, key_kind=None, value_kind=None):
if (key_kind is not None and value_kind is not None):
ReferenceKind.__init__(self,
'm[' + key_kind.spec + '][' + value_kind.spec +
']')
ReferenceKind.__init__(
self, 'm[' + key_kind.spec + '][' + value_kind.spec + ']')
if IsNullableKind(key_kind):
raise Exception("Nullable kinds cannot be keys in maps.")
if IsAnyHandleKind(key_kind):
......@@ -588,7 +607,11 @@ class AssociatedInterfaceRequest(ReferenceKind):
class Parameter(object):
def __init__(self, mojom_name=None, kind=None, ordinal=None, default=None,
def __init__(self,
mojom_name=None,
kind=None,
ordinal=None,
default=None,
attributes=None):
self.mojom_name = mojom_name
self.ordinal = ordinal
......@@ -624,16 +647,27 @@ class Method(object):
if as_ref:
return '<%s mojom_name=%r>' % (self.__class__.__name__, self.mojom_name)
else:
return GenericRepr(self, {'mojom_name': False, 'parameters': True,
'response_parameters': True})
def AddParameter(self, mojom_name, kind, ordinal=None, default=None,
return GenericRepr(self, {
'mojom_name': False,
'parameters': True,
'response_parameters': True
})
def AddParameter(self,
mojom_name,
kind,
ordinal=None,
default=None,
attributes=None):
parameter = Parameter(mojom_name, kind, ordinal, default, attributes)
self.parameters.append(parameter)
return parameter
def AddResponseParameter(self, mojom_name, kind, ordinal=None, default=None,
def AddResponseParameter(self,
mojom_name,
kind,
ordinal=None,
default=None,
attributes=None):
if self.response_parameters == None:
self.response_parameters = []
......@@ -689,8 +723,11 @@ class Interface(ReferenceKind):
if as_ref:
return '<%s mojom_name=%r>' % (self.__class__.__name__, self.mojom_name)
else:
return GenericRepr(self, {'mojom_name': False, 'attributes': False,
'methods': False})
return GenericRepr(self, {
'mojom_name': False,
'attributes': False,
'methods': False
})
def AddMethod(self, mojom_name, ordinal=None, attributes=None):
method = Method(self, mojom_name, ordinal, attributes)
......@@ -723,7 +760,10 @@ class AssociatedInterface(ReferenceKind):
class EnumField(object):
def __init__(self, mojom_name=None, value=None, attributes=None,
def __init__(self,
mojom_name=None,
value=None,
attributes=None,
numeric_value=None):
self.mojom_name = mojom_name
self.value = value
......@@ -771,8 +811,7 @@ class Enum(Kind):
class Module(object):
def __init__(self, path=None, mojom_namespace=None,
attributes=None):
def __init__(self, path=None, mojom_namespace=None, attributes=None):
self.path = path
self.mojom_namespace = mojom_namespace
self.structs = []
......@@ -794,9 +833,15 @@ class Module(object):
return '<%s path=%r mojom_namespace=%r>' % (
self.__class__.__name__, self.path, self.mojom_namespace)
else:
return GenericRepr(self, {'path': False, 'mojom_namespace': False,
'attributes': False, 'structs': False,
'interfaces': False, 'unions': False})
return GenericRepr(
self, {
'path': False,
'mojom_namespace': False,
'attributes': False,
'structs': False,
'interfaces': False,
'unions': False
})
def AddInterface(self, mojom_name, attributes=None):
interface = Interface(mojom_name, self, attributes)
......@@ -843,15 +888,11 @@ def IsDoubleKind(kind):
def IsIntegralKind(kind):
return (kind.spec == BOOL.spec or
kind.spec == INT8.spec or
kind.spec == INT16.spec or
kind.spec == INT32.spec or
kind.spec == INT64.spec or
kind.spec == UINT8.spec or
kind.spec == UINT16.spec or
kind.spec == UINT32.spec or
kind.spec == UINT64.spec)
return (kind.spec == BOOL.spec or kind.spec == INT8.spec
or kind.spec == INT16.spec or kind.spec == INT32.spec
or kind.spec == INT64.spec or kind.spec == UINT8.spec
or kind.spec == UINT16.spec or kind.spec == UINT32.spec
or kind.spec == UINT64.spec)
def IsStringKind(kind):
......@@ -875,13 +916,13 @@ def IsMessagePipeKind(kind):
def IsSharedBufferKind(kind):
return (kind.spec == SHAREDBUFFER.spec or
kind.spec == NULLABLE_SHAREDBUFFER.spec)
return (kind.spec == SHAREDBUFFER.spec
or kind.spec == NULLABLE_SHAREDBUFFER.spec)
def IsPlatformHandleKind(kind):
return (kind.spec == PLATFORMHANDLE.spec or
kind.spec == NULLABLE_PLATFORMHANDLE.spec)
return (kind.spec == PLATFORMHANDLE.spec
or kind.spec == NULLABLE_PLATFORMHANDLE.spec)
def IsStructKind(kind):
......@@ -911,6 +952,7 @@ def IsInterfaceRequestKind(kind):
def IsAssociatedInterfaceRequestKind(kind):
return isinstance(kind, AssociatedInterfaceRequest)
def IsPendingRemoteKind(kind):
return isinstance(kind, PendingRemote)
......@@ -948,24 +990,21 @@ def IsObjectKind(kind):
def IsPointerKind(kind):
return (IsStructKind(kind) or IsArrayKind(kind) or IsStringKind(kind) or
IsMapKind(kind))
return (IsStructKind(kind) or IsArrayKind(kind) or IsStringKind(kind)
or IsMapKind(kind))
# Please note that it doesn't include any interface kind.
def IsAnyHandleKind(kind):
return (IsGenericHandleKind(kind) or
IsDataPipeConsumerKind(kind) or
IsDataPipeProducerKind(kind) or
IsMessagePipeKind(kind) or
IsSharedBufferKind(kind) or
IsPlatformHandleKind(kind))
return (IsGenericHandleKind(kind) or IsDataPipeConsumerKind(kind)
or IsDataPipeProducerKind(kind) or IsMessagePipeKind(kind)
or IsSharedBufferKind(kind) or IsPlatformHandleKind(kind))
def IsAnyInterfaceKind(kind):
return (IsInterfaceKind(kind) or IsInterfaceRequestKind(kind) or
IsAssociatedKind(kind) or IsPendingRemoteKind(kind) or
IsPendingReceiverKind(kind))
return (IsInterfaceKind(kind) or IsInterfaceRequestKind(kind)
or IsAssociatedKind(kind) or IsPendingRemoteKind(kind)
or IsPendingReceiverKind(kind))
def IsAnyHandleOrInterfaceKind(kind):
......@@ -973,10 +1012,10 @@ def IsAnyHandleOrInterfaceKind(kind):
def IsAssociatedKind(kind):
return (IsAssociatedInterfaceKind(kind) or
IsAssociatedInterfaceRequestKind(kind) or
IsPendingAssociatedRemoteKind(kind) or
IsPendingAssociatedReceiverKind(kind))
return (IsAssociatedInterfaceKind(kind)
or IsAssociatedInterfaceRequestKind(kind)
or IsPendingAssociatedRemoteKind(kind)
or IsPendingAssociatedReceiverKind(kind))
def HasCallbacks(interface):
......@@ -1011,7 +1050,7 @@ def _AnyMethodParameterRecursive(method, predicate, visited_kinds=None):
if _HasProperty(field.kind):
return True
if IsMapKind(kind):
if _HasProperty(kind.key_kind) or _HasProperty(kind.value_kind):
if _HasProperty(kind.key_kind) or _HasProperty(kind.value_kind):
return True
return False
......@@ -1031,8 +1070,8 @@ def _AnyMethodParameterRecursive(method, predicate, visited_kinds=None):
# Finds out whether a method passes associated interfaces and associated
# interface requests.
def MethodPassesAssociatedKinds(method, visited_kinds=None):
return _AnyMethodParameterRecursive(method, IsAssociatedKind,
visited_kinds=visited_kinds)
return _AnyMethodParameterRecursive(
method, IsAssociatedKind, visited_kinds=visited_kinds)
# Determines whether a method passes interfaces.
......@@ -1062,6 +1101,7 @@ def ContainsHandlesOrInterfaces(kind):
# We remember the types we already checked to avoid infinite recursion when
# checking recursive (or mutually recursive) types:
checked = set()
def Check(kind):
if kind.spec in checked:
return False
......@@ -1080,6 +1120,7 @@ def ContainsHandlesOrInterfaces(kind):
return Check(kind.key_kind) or Check(kind.value_kind)
else:
return False
return Check(kind)
......@@ -1098,6 +1139,7 @@ def ContainsNativeTypes(kind):
# We remember the types we already checked to avoid infinite recursion when
# checking recursive (or mutually recursive) types:
checked = set()
def Check(kind):
if kind.spec in checked:
return False
......@@ -1120,4 +1162,5 @@ def ContainsNativeTypes(kind):
return Check(kind.key_kind) or Check(kind.value_kind)
else:
return False
return Check(kind)
......@@ -14,47 +14,49 @@ import mojom.generate.module as mojom
# Size of struct header in bytes: num_bytes [4B] + version [4B].
HEADER_SIZE = 8
class PackedField(object):
kind_to_size = {
mojom.BOOL: 1,
mojom.INT8: 1,
mojom.UINT8: 1,
mojom.INT16: 2,
mojom.UINT16: 2,
mojom.INT32: 4,
mojom.UINT32: 4,
mojom.FLOAT: 4,
mojom.HANDLE: 4,
mojom.MSGPIPE: 4,
mojom.SHAREDBUFFER: 4,
mojom.PLATFORMHANDLE: 4,
mojom.DCPIPE: 4,
mojom.DPPIPE: 4,
mojom.NULLABLE_HANDLE: 4,
mojom.NULLABLE_MSGPIPE: 4,
mojom.NULLABLE_SHAREDBUFFER: 4,
mojom.NULLABLE_PLATFORMHANDLE: 4,
mojom.NULLABLE_DCPIPE: 4,
mojom.NULLABLE_DPPIPE: 4,
mojom.INT64: 8,
mojom.UINT64: 8,
mojom.DOUBLE: 8,
mojom.STRING: 8,
mojom.NULLABLE_STRING: 8
mojom.BOOL: 1,
mojom.INT8: 1,
mojom.UINT8: 1,
mojom.INT16: 2,
mojom.UINT16: 2,
mojom.INT32: 4,
mojom.UINT32: 4,
mojom.FLOAT: 4,
mojom.HANDLE: 4,
mojom.MSGPIPE: 4,
mojom.SHAREDBUFFER: 4,
mojom.PLATFORMHANDLE: 4,
mojom.DCPIPE: 4,
mojom.DPPIPE: 4,
mojom.NULLABLE_HANDLE: 4,
mojom.NULLABLE_MSGPIPE: 4,
mojom.NULLABLE_SHAREDBUFFER: 4,
mojom.NULLABLE_PLATFORMHANDLE: 4,
mojom.NULLABLE_DCPIPE: 4,
mojom.NULLABLE_DPPIPE: 4,
mojom.INT64: 8,
mojom.UINT64: 8,
mojom.DOUBLE: 8,
mojom.STRING: 8,
mojom.NULLABLE_STRING: 8
}
@classmethod
def GetSizeForKind(cls, kind):
if isinstance(kind, (mojom.Array, mojom.Map, mojom.Struct,
mojom.Interface, mojom.AssociatedInterface,
mojom.PendingRemote, mojom.PendingAssociatedRemote)):
if isinstance(kind, (mojom.Array, mojom.Map, mojom.Struct, mojom.Interface,
mojom.AssociatedInterface, mojom.PendingRemote,
mojom.PendingAssociatedRemote)):
return 8
if isinstance(kind, mojom.Union):
return 16
if isinstance(kind, (mojom.InterfaceRequest, mojom.PendingReceiver)):
kind = mojom.MSGPIPE
if isinstance(kind, (mojom.AssociatedInterfaceRequest,
mojom.PendingAssociatedReceiver)):
if isinstance(
kind,
(mojom.AssociatedInterfaceRequest, mojom.PendingAssociatedReceiver)):
return 4
if isinstance(kind, mojom.Enum):
# TODO(mpcomplete): what about big enums?
......@@ -98,9 +100,8 @@ def GetPad(offset, alignment):
def GetFieldOffset(field, last_field):
"""Returns a 2-tuple of the field offset and bit (for BOOLs)."""
if (field.field.kind == mojom.BOOL and
last_field.field.kind == mojom.BOOL and
last_field.bit < 7):
if (field.field.kind == mojom.BOOL and last_field.field.kind == mojom.BOOL
and last_field.bit < 7):
return (last_field.offset, last_field.bit + 1)
offset = last_field.offset + last_field.size
......@@ -152,13 +153,13 @@ class PackedStruct(object):
next_min_version = packed_field.field.min_version
packed_field.min_version = next_min_version
if (packed_field.min_version != 0 and
mojom.IsReferenceKind(packed_field.field.kind) and
not packed_field.field.kind.is_nullable):
if (packed_field.min_version != 0
and mojom.IsReferenceKind(packed_field.field.kind)
and not packed_field.field.kind.is_nullable):
raise Exception("Non-nullable fields are only allowed in version 0 of "
"a struct. %s.%s is defined with [MinVersion=%d]."
% (self.struct.name, packed_field.field.name,
packed_field.min_version))
"a struct. %s.%s is defined with [MinVersion=%d]." %
(self.struct.name, packed_field.field.name,
packed_field.min_version))
src_field = src_fields[0]
src_field.offset = 0
......@@ -247,10 +248,11 @@ def GetVersionInfo(packed_struct):
# The fields are iterated in ordinal order here. However, the size of a
# version is determined by the last field of that version in pack order,
# instead of ordinal order. Therefore, we need to calculate the max value.
last_payload_size = max(GetPayloadSizeUpToField(packed_field),
last_payload_size)
last_payload_size = max(
GetPayloadSizeUpToField(packed_field), last_payload_size)
assert len(versions) == 0 or last_num_fields != versions[-1].num_fields
versions.append(VersionInfo(last_version, last_num_fields,
last_payload_size + HEADER_SIZE))
versions.append(
VersionInfo(last_version, last_num_fields,
last_payload_size + HEADER_SIZE))
return versions
......@@ -16,57 +16,66 @@ import jinja2
def ApplyTemplate(mojo_generator, path_to_template, params, **kwargs):
loader = jinja2.ModuleLoader(os.path.join(
mojo_generator.bytecode_path, "%s.zip" % mojo_generator.GetTemplatePrefix(
)))
loader = jinja2.ModuleLoader(
os.path.join(mojo_generator.bytecode_path,
"%s.zip" % mojo_generator.GetTemplatePrefix()))
final_kwargs = dict(mojo_generator.GetJinjaParameters())
final_kwargs.update(kwargs)
jinja_env = jinja2.Environment(loader=loader,
keep_trailing_newline=True,
**final_kwargs)
jinja_env = jinja2.Environment(
loader=loader, keep_trailing_newline=True, **final_kwargs)
jinja_env.globals.update(mojo_generator.GetGlobals())
jinja_env.filters.update(mojo_generator.GetFilters())
template = jinja_env.get_template(path_to_template)
return template.render(params)
def UseJinja(path_to_template, **kwargs):
def RealDecorator(generator):
def GeneratorInternal(*args, **kwargs2):
parameters = generator(*args, **kwargs2)
return ApplyTemplate(args[0], path_to_template, parameters, **kwargs)
GeneratorInternal.__name__ = generator.__name__
return GeneratorInternal
return RealDecorator
def ApplyImportedTemplate(mojo_generator, path_to_template, filename, params, **kwargs):
def ApplyImportedTemplate(mojo_generator, path_to_template, filename, params,
**kwargs):
loader = jinja2.FileSystemLoader(searchpath=path_to_template)
final_kwargs = dict(mojo_generator.GetJinjaParameters())
final_kwargs.update(kwargs)
jinja_env = jinja2.Environment(loader=loader,
keep_trailing_newline=True,
**final_kwargs)
jinja_env = jinja2.Environment(
loader=loader, keep_trailing_newline=True, **final_kwargs)
jinja_env.globals.update(mojo_generator.GetGlobals())
jinja_env.filters.update(mojo_generator.GetFilters())
template = jinja_env.get_template(filename)
return template.render(params)
def UseJinjaForImportedTemplate(func):
def wrapper(*args, **kwargs):
parameters = func(*args, **kwargs)
path_to_template = args[1]
filename = args[2]
return ApplyImportedTemplate(args[0], path_to_template, filename, parameters)
return ApplyImportedTemplate(args[0], path_to_template, filename,
parameters)
wrapper.__name__ = func.__name__
return wrapper
def PrecompileTemplates(generator_modules, output_dir):
for module in generator_modules.values():
generator = module.Generator(None)
jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader([os.path.join(
os.path.dirname(module.__file__), generator.GetTemplatePrefix())]))
jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader([
os.path.join(
os.path.dirname(module.__file__), generator.GetTemplatePrefix())
]))
jinja_env.filters.update(generator.GetFilters())
jinja_env.compile_templates(
os.path.join(output_dir, "%s.zip" % generator.GetTemplatePrefix()),
......
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Convert parse tree to AST.
This module converts the parse tree to the AST we use for code generation. The
......@@ -17,6 +16,7 @@ import re
import mojom.generate.module as mojom
from mojom.parse import ast
def _DuplicateName(values):
"""Returns the 'mojom_name' of the first entry in |values| whose 'mojom_name'
has already been encountered. If there are no duplicates, returns None."""
......@@ -27,6 +27,7 @@ def _DuplicateName(values):
names.add(value.mojom_name)
return None
def _ElemsOfType(elems, elem_type, scope):
"""Find all elements of the given type.
......@@ -48,25 +49,28 @@ def _ElemsOfType(elems, elem_type, scope):
(duplicate_name, scope))
return result
def _MapKind(kind):
map_to_kind = {'bool': 'b',
'int8': 'i8',
'int16': 'i16',
'int32': 'i32',
'int64': 'i64',
'uint8': 'u8',
'uint16': 'u16',
'uint32': 'u32',
'uint64': 'u64',
'float': 'f',
'double': 'd',
'string': 's',
'handle': 'h',
'handle<data_pipe_consumer>': 'h:d:c',
'handle<data_pipe_producer>': 'h:d:p',
'handle<message_pipe>': 'h:m',
'handle<shared_buffer>': 'h:s',
'handle<platform>': 'h:p'}
map_to_kind = {
'bool': 'b',
'int8': 'i8',
'int16': 'i16',
'int32': 'i32',
'int64': 'i64',
'uint8': 'u8',
'uint16': 'u16',
'uint32': 'u32',
'uint64': 'u64',
'float': 'f',
'double': 'd',
'string': 's',
'handle': 'h',
'handle<data_pipe_consumer>': 'h:d:c',
'handle<data_pipe_producer>': 'h:d:p',
'handle<message_pipe>': 'h:m',
'handle<shared_buffer>': 'h:s',
'handle<platform>': 'h:p'
}
if kind.endswith('?'):
base_kind = _MapKind(kind[0:-1])
# NOTE: This doesn't rule out enum types. Those will be detected later, when
......@@ -74,17 +78,16 @@ def _MapKind(kind):
reference_kinds = ('m', 's', 'h', 'a', 'r', 'x', 'asso', 'rmt', 'rcv',
'rma', 'rca')
if re.split('[^a-z]', base_kind, 1)[0] not in reference_kinds:
raise Exception(
'A type (spec "%s") cannot be made nullable' % base_kind)
raise Exception('A type (spec "%s") cannot be made nullable' % base_kind)
return '?' + base_kind
if kind.endswith('}'):
lbracket = kind.rfind('{')
value = kind[0:lbracket]
return 'm[' + _MapKind(kind[lbracket+1:-1]) + '][' + _MapKind(value) + ']'
return 'm[' + _MapKind(kind[lbracket + 1:-1]) + '][' + _MapKind(value) + ']'
if kind.endswith(']'):
lbracket = kind.rfind('[')
typename = kind[0:lbracket]
return 'a' + kind[lbracket+1:-1] + ':' + _MapKind(typename)
return 'a' + kind[lbracket + 1:-1] + ':' + _MapKind(typename)
if kind.endswith('&'):
return 'r:' + _MapKind(kind[0:-1])
if kind.startswith('asso<'):
......@@ -106,25 +109,26 @@ def _MapKind(kind):
return map_to_kind[kind]
return 'x:' + kind
def _AttributeListToDict(attribute_list):
if attribute_list is None:
return None
assert isinstance(attribute_list, ast.AttributeList)
# TODO(vtl): Check for duplicate keys here.
return dict([(attribute.key, attribute.value)
for attribute in attribute_list])
return dict(
[(attribute.key, attribute.value) for attribute in attribute_list])
builtin_values = frozenset([
"double.INFINITY",
"double.NEGATIVE_INFINITY",
"double.NAN",
"float.INFINITY",
"float.NEGATIVE_INFINITY",
"float.NAN"])
"double.INFINITY", "double.NEGATIVE_INFINITY", "double.NAN",
"float.INFINITY", "float.NEGATIVE_INFINITY", "float.NAN"
])
def _IsBuiltinValue(value):
return value in builtin_values
def _LookupKind(kinds, spec, scope):
"""Tries to find which Kind a spec refers to, given the scope in which its
referenced. Starts checking from the narrowest scope to most general. For
......@@ -148,6 +152,7 @@ def _LookupKind(kinds, spec, scope):
return kinds.get(spec)
def _LookupValue(values, mojom_name, scope, kind):
"""Like LookupKind, but for constant values."""
# If the type is an enum, the value can be specified as a qualified name, in
......@@ -167,6 +172,7 @@ def _LookupValue(values, mojom_name, scope, kind):
return values.get(mojom_name)
def _FixupExpression(module, value, scope, kind):
"""Translates an IDENTIFIER into a built-in value or structured NamedValue
object."""
......@@ -181,6 +187,7 @@ def _FixupExpression(module, value, scope, kind):
return mojom.BuiltinValue(value[1])
return value
def _Kind(kinds, spec, scope):
"""Convert a type name into a mojom.Kind object.
......@@ -214,7 +221,7 @@ def _Kind(kinds, spec, scope):
elif spec.startswith('a'):
colon = spec.find(':')
length = int(spec[1:colon])
kind = mojom.Array(_Kind(kinds, spec[colon+1:], scope), length)
kind = mojom.Array(_Kind(kinds, spec[colon + 1:], scope), length)
elif spec.startswith('r:'):
kind = mojom.InterfaceRequest(_Kind(kinds, spec[2:], scope))
elif spec.startswith('rmt:'):
......@@ -232,25 +239,26 @@ def _Kind(kinds, spec, scope):
# inside the key type spec.
key_end = spec.find(']')
assert key_end != -1 and key_end < len(spec) - 1
assert spec[key_end+1] == '[' and spec[-1] == ']'
assert spec[key_end + 1] == '[' and spec[-1] == ']'
first_kind = spec[2:key_end]
second_kind = spec[key_end+2:-1]
second_kind = spec[key_end + 2:-1]
kind = mojom.Map(_Kind(kinds, first_kind, scope),
_Kind(kinds, second_kind, scope))
kind = mojom.Map(
_Kind(kinds, first_kind, scope), _Kind(kinds, second_kind, scope))
else:
kind = mojom.Kind(spec)
kinds[spec] = kind
return kind
def _Import(module, import_module):
# Copy the struct kinds from our imports into the current module.
importable_kinds = (mojom.Struct, mojom.Union, mojom.Enum, mojom.Interface)
for kind in import_module.kinds.values():
if (isinstance(kind, importable_kinds) and
kind.module.path == import_module.path):
if (isinstance(kind, importable_kinds)
and kind.module.path == import_module.path):
module.kinds[kind.spec] = kind
# Ditto for values.
for value in import_module.values.values():
......@@ -259,6 +267,7 @@ def _Import(module, import_module):
return import_module
def _Struct(module, parsed_struct):
"""
Args:
......@@ -287,8 +296,8 @@ def _Struct(module, parsed_struct):
lambda constant: _Constant(module, constant, struct),
_ElemsOfType(parsed_struct.body, ast.Const, parsed_struct.mojom_name))
# Stash fields parsed_struct here temporarily.
struct.fields_data = _ElemsOfType(
parsed_struct.body, ast.StructField, parsed_struct.mojom_name)
struct.fields_data = _ElemsOfType(parsed_struct.body, ast.StructField,
parsed_struct.mojom_name)
struct.attributes = _AttributeListToDict(parsed_struct.attribute_list)
# Enforce that a [Native] attribute is set to make native-only struct
......@@ -303,6 +312,7 @@ def _Struct(module, parsed_struct):
return struct
def _Union(module, parsed_union):
"""
Args:
......@@ -317,11 +327,12 @@ def _Union(module, parsed_union):
union.spec = 'x:' + module.mojom_namespace + '.' + union.mojom_name
module.kinds[union.spec] = union
# Stash fields parsed_union here temporarily.
union.fields_data = _ElemsOfType(
parsed_union.body, ast.UnionField, parsed_union.mojom_name)
union.fields_data = _ElemsOfType(parsed_union.body, ast.UnionField,
parsed_union.mojom_name)
union.attributes = _AttributeListToDict(parsed_union.attribute_list)
return union
def _StructField(module, parsed_field, struct):
"""
Args:
......@@ -334,16 +345,16 @@ def _StructField(module, parsed_field, struct):
"""
field = mojom.StructField()
field.mojom_name = parsed_field.mojom_name
field.kind = _Kind(
module.kinds, _MapKind(parsed_field.typename),
(module.mojom_namespace, struct.mojom_name))
field.kind = _Kind(module.kinds, _MapKind(parsed_field.typename),
(module.mojom_namespace, struct.mojom_name))
field.ordinal = parsed_field.ordinal.value if parsed_field.ordinal else None
field.default = _FixupExpression(
module, parsed_field.default_value,
(module.mojom_namespace, struct.mojom_name), field.kind)
field.default = _FixupExpression(module, parsed_field.default_value,
(module.mojom_namespace, struct.mojom_name),
field.kind)
field.attributes = _AttributeListToDict(parsed_field.attribute_list)
return field
def _UnionField(module, parsed_field, union):
"""
Args:
......@@ -356,15 +367,15 @@ def _UnionField(module, parsed_field, union):
"""
field = mojom.UnionField()
field.mojom_name = parsed_field.mojom_name
field.kind = _Kind(
module.kinds, _MapKind(parsed_field.typename),
(module.mojom_namespace, union.mojom_name))
field.kind = _Kind(module.kinds, _MapKind(parsed_field.typename),
(module.mojom_namespace, union.mojom_name))
field.ordinal = parsed_field.ordinal.value if parsed_field.ordinal else None
field.default = _FixupExpression(
module, None, (module.mojom_namespace, union.mojom_name), field.kind)
field.attributes = _AttributeListToDict(parsed_field.attribute_list)
return field
def _Parameter(module, parsed_param, interface):
"""
Args:
......@@ -377,15 +388,15 @@ def _Parameter(module, parsed_param, interface):
"""
parameter = mojom.Parameter()
parameter.mojom_name = parsed_param.mojom_name
parameter.kind = _Kind(
module.kinds, _MapKind(parsed_param.typename),
(module.mojom_namespace, interface.mojom_name))
parameter.ordinal = (
parsed_param.ordinal.value if parsed_param.ordinal else None)
parameter.kind = _Kind(module.kinds, _MapKind(parsed_param.typename),
(module.mojom_namespace, interface.mojom_name))
parameter.ordinal = (parsed_param.ordinal.value
if parsed_param.ordinal else None)
parameter.default = None # TODO(tibell): We never have these. Remove field?
parameter.attributes = _AttributeListToDict(parsed_param.attribute_list)
return parameter
def _Method(module, parsed_method, interface):
"""
Args:
......@@ -397,7 +408,8 @@ def _Method(module, parsed_method, interface):
{mojom.Method} AST method.
"""
method = mojom.Method(
interface, parsed_method.mojom_name,
interface,
parsed_method.mojom_name,
ordinal=parsed_method.ordinal.value if parsed_method.ordinal else None)
method.parameters = list(
map(lambda parameter: _Parameter(module, parameter, interface),
......@@ -417,6 +429,7 @@ def _Method(module, parsed_method, interface):
return method
def _Interface(module, parsed_iface):
"""
Args:
......@@ -437,11 +450,12 @@ def _Interface(module, parsed_iface):
lambda constant: _Constant(module, constant, interface),
_ElemsOfType(parsed_iface.body, ast.Const, parsed_iface.mojom_name))
# Stash methods parsed_iface here temporarily.
interface.methods_data = _ElemsOfType(
parsed_iface.body, ast.Method, parsed_iface.mojom_name)
interface.methods_data = _ElemsOfType(parsed_iface.body, ast.Method,
parsed_iface.mojom_name)
interface.attributes = _AttributeListToDict(parsed_iface.attribute_list)
return interface
def _EnumField(module, enum, parsed_field, parent_kind):
"""
Args:
......@@ -464,13 +478,14 @@ def _EnumField(module, enum, parsed_field, parent_kind):
module, parsed_field.value,
(module.mojom_namespace, parent_kind.mojom_name), enum)
else:
field.value = _FixupExpression(
module, parsed_field.value, (module.mojom_namespace, ), enum)
field.value = _FixupExpression(module, parsed_field.value,
(module.mojom_namespace, ), enum)
field.attributes = _AttributeListToDict(parsed_field.attribute_list)
value = mojom.EnumValue(module, enum, field)
module.values[value.GetSpec()] = value
return field
def _ResolveNumericEnumValues(enum_fields):
"""
Given a reference to a list of mojom.EnumField, resolves and assigns their
......@@ -510,6 +525,7 @@ def _ResolveNumericEnumValues(enum_fields):
return min_value, max_value
def _Enum(module, parsed_enum, parent_kind):
"""
Args:
......@@ -545,6 +561,7 @@ def _Enum(module, parsed_enum, parent_kind):
return enum
def _Constant(module, parsed_const, parent_kind):
"""
Args:
......@@ -584,21 +601,20 @@ def _CollectReferencedKinds(module, all_defined_kinds):
return extract_referenced_user_kinds(kind.kind)
if mojom.IsMapKind(kind):
return (extract_referenced_user_kinds(kind.key_kind) +
extract_referenced_user_kinds(kind.value_kind))
extract_referenced_user_kinds(kind.value_kind))
if mojom.IsInterfaceRequestKind(kind) or mojom.IsAssociatedKind(kind):
return [kind.kind]
if mojom.IsStructKind(kind):
return [kind]
if (mojom.IsInterfaceKind(kind) or mojom.IsEnumKind(kind) or
mojom.IsUnionKind(kind)):
if (mojom.IsInterfaceKind(kind) or mojom.IsEnumKind(kind)
or mojom.IsUnionKind(kind)):
return [kind]
return []
def sanitize_kind(kind):
"""Removes nullability from a kind"""
if kind.spec.startswith('?'):
return _Kind(module.kinds, kind.spec[1:],
(module.mojom_namespace, ''))
return _Kind(module.kinds, kind.spec[1:], (module.mojom_namespace, ''))
return kind
referenced_user_kinds = {}
......@@ -614,9 +630,9 @@ def _CollectReferencedKinds(module, all_defined_kinds):
for method in interface.methods:
for param in itertools.chain(method.parameters or [],
method.response_parameters or []):
if (mojom.IsStructKind(param.kind) or mojom.IsUnionKind(param.kind) or
mojom.IsEnumKind(param.kind) or
mojom.IsAnyInterfaceKind(param.kind)):
if (mojom.IsStructKind(param.kind) or mojom.IsUnionKind(param.kind)
or mojom.IsEnumKind(param.kind)
or mojom.IsAnyInterfaceKind(param.kind)):
for referenced_kind in extract_referenced_user_kinds(param.kind):
sanitized_kind = sanitize_kind(referenced_kind)
referenced_user_kinds[sanitized_kind.spec] = sanitized_kind
......@@ -646,8 +662,8 @@ def _Module(tree, path, imports):
# Imports must come first, because they add to module.kinds which is used
# by by the others.
module.imports = [
_Import(module, imports[imp.import_filename])
for imp in tree.import_list]
_Import(module, imports[imp.import_filename]) for imp in tree.import_list
]
if tree.module and tree.module.attribute_list:
assert isinstance(tree.module.attribute_list, ast.AttributeList)
# TODO(vtl): Check for duplicate keys here.
......@@ -703,11 +719,12 @@ def _Module(tree, path, imports):
all_defined_kinds.values())
imported_kind_specs = set(all_referenced_kinds.keys()).difference(
set(all_defined_kinds.keys()))
module.imported_kinds = dict((spec, all_referenced_kinds[spec])
for spec in imported_kind_specs)
module.imported_kinds = dict(
(spec, all_referenced_kinds[spec]) for spec in imported_kind_specs)
return module
def OrderedModule(tree, path, imports):
"""Convert parse tree to AST module.
......
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Node classes for the AST for a Mojo IDL file."""
# Note: For convenience of testing, you probably want to define __eq__() methods
......@@ -393,7 +392,6 @@ class Union(Definition):
class UnionField(Definition):
def __init__(self, mojom_name, attribute_list, ordinal, typename, **kwargs):
assert isinstance(mojom_name, str)
assert attribute_list is None or isinstance(attribute_list, AttributeList)
......
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Helpers for processing conditionally enabled features in a mojom."""
from . import ast
from ..error import Error
class EnableIfError(Error):
""" Class for errors from ."""
def __init__(self, filename, message, lineno=None):
Error.__init__(self, filename, message, lineno=lineno, addenda=None)
def _IsEnabled(definition, enabled_features):
"""Returns true if a definition is enabled.
......@@ -28,9 +29,10 @@ def _IsEnabled(definition, enabled_features):
for a in definition.attribute_list:
if a.key == 'EnableIf':
if already_defined:
raise EnableIfError(definition.filename,
"EnableIf attribute may only be defined once per field.",
definition.lineno)
raise EnableIfError(
definition.filename,
"EnableIf attribute may only be defined once per field.",
definition.lineno)
already_defined = True
for attribute in definition.attribute_list:
......@@ -69,12 +71,12 @@ def _FilterDefinition(definition, enabled_features):
def RemoveDisabledDefinitions(mojom, enabled_features):
"""Removes conditionally disabled definitions from a Mojom node."""
mojom.import_list = ast.ImportList([
imported_file for imported_file in mojom.import_list
imported_file for imported_file in mojom.import_list
if _IsEnabled(imported_file, enabled_features)
])
mojom.definition_list = [
definition for definition in mojom.definition_list
if _IsEnabled(definition, enabled_features)
if _IsEnabled(definition, enabled_features)
]
for definition in mojom.definition_list:
_FilterDefinition(definition, enabled_features)
......@@ -6,6 +6,7 @@ import imp
import os.path
import sys
def _GetDirAbove(dirname):
"""Returns the directory "above" this file containing |dirname| (which must
also be "above" this file)."""
......@@ -16,6 +17,7 @@ def _GetDirAbove(dirname):
if tail == dirname:
return path
try:
imp.find_module("ply")
except ImportError:
......@@ -35,7 +37,6 @@ class LexError(Error):
# We have methods which look like they could be functions:
# pylint: disable=R0201
class Lexer(object):
def __init__(self, filename):
self.filename = filename
......@@ -51,25 +52,24 @@ class Lexer(object):
## Reserved keywords
##
keywords = (
'HANDLE',
'IMPORT',
'MODULE',
'STRUCT',
'UNION',
'INTERFACE',
'ENUM',
'CONST',
'TRUE',
'FALSE',
'DEFAULT',
'ARRAY',
'MAP',
'ASSOCIATED',
'PENDING_REMOTE',
'PENDING_RECEIVER',
'PENDING_ASSOCIATED_REMOTE',
'PENDING_ASSOCIATED_RECEIVER',
'HANDLE',
'IMPORT',
'MODULE',
'STRUCT',
'UNION',
'INTERFACE',
'ENUM',
'CONST',
'TRUE',
'FALSE',
'DEFAULT',
'ARRAY',
'MAP',
'ASSOCIATED',
'PENDING_REMOTE',
'PENDING_RECEIVER',
'PENDING_ASSOCIATED_REMOTE',
'PENDING_ASSOCIATED_RECEIVER',
)
keyword_map = {}
......@@ -80,36 +80,42 @@ class Lexer(object):
## All the tokens recognized by the lexer
##
tokens = keywords + (
# Identifiers
'NAME',
# Constants
'ORDINAL',
'INT_CONST_DEC', 'INT_CONST_HEX',
'FLOAT_CONST',
# String literals
'STRING_LITERAL',
# Operators
'MINUS',
'PLUS',
'AMP',
'QSTN',
# Assignment
'EQUALS',
# Request / response
'RESPONSE',
# Delimiters
'LPAREN', 'RPAREN', # ( )
'LBRACKET', 'RBRACKET', # [ ]
'LBRACE', 'RBRACE', # { }
'LANGLE', 'RANGLE', # < >
'SEMI', # ;
'COMMA', 'DOT' # , .
# Identifiers
'NAME',
# Constants
'ORDINAL',
'INT_CONST_DEC',
'INT_CONST_HEX',
'FLOAT_CONST',
# String literals
'STRING_LITERAL',
# Operators
'MINUS',
'PLUS',
'AMP',
'QSTN',
# Assignment
'EQUALS',
# Request / response
'RESPONSE',
# Delimiters
'LPAREN',
'RPAREN', # ( )
'LBRACKET',
'RBRACKET', # [ ]
'LBRACE',
'RBRACE', # { }
'LANGLE',
'RANGLE', # < >
'SEMI', # ;
'COMMA',
'DOT' # , .
)
##
......@@ -124,7 +130,7 @@ class Lexer(object):
# integer constants (K&R2: A.2.5.1)
decimal_constant = '0|([1-9][0-9]*)'
hex_constant = hex_prefix+hex_digits
hex_constant = hex_prefix + hex_digits
# Don't allow octal constants (even invalid octal).
octal_constant_disallowed = '0[0-9]+'
......@@ -144,9 +150,9 @@ class Lexer(object):
r"""(\\("""+simple_escape+'|'+decimal_escape+'|'+hex_escape+'))'
# string literals (K&R2: A.2.6)
string_char = r"""([^"\\\n]|"""+escape_sequence+')'
string_literal = '"'+string_char+'*"'
bad_string_literal = '"'+string_char+'*'+bad_escape+string_char+'*"'
string_char = r"""([^"\\\n]|""" + escape_sequence + ')'
string_literal = '"' + string_char + '*"'
bad_string_literal = '"' + string_char + '*' + bad_escape + string_char + '*"'
# floating constants (K&R2: A.2.5.3)
exponent_part = r"""([eE][-+]?[0-9]+)"""
......@@ -160,7 +166,8 @@ class Lexer(object):
missing_ordinal_value = r'@'
# Don't allow ordinal values in octal (even invalid octal, like 09) or
# hexadecimal.
octal_or_hex_ordinal_disallowed = r'@((0[0-9]+)|('+hex_prefix+hex_digits+'))'
octal_or_hex_ordinal_disallowed = (
r'@((0[0-9]+)|(' + hex_prefix + hex_digits + '))')
##
## Rules for the normal state
......@@ -173,31 +180,31 @@ class Lexer(object):
t.lexer.lineno += len(t.value)
# Operators
t_MINUS = r'-'
t_PLUS = r'\+'
t_AMP = r'&'
t_QSTN = r'\?'
t_MINUS = r'-'
t_PLUS = r'\+'
t_AMP = r'&'
t_QSTN = r'\?'
# =
t_EQUALS = r'='
t_EQUALS = r'='
# =>
t_RESPONSE = r'=>'
t_RESPONSE = r'=>'
# Delimiters
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_LBRACKET = r'\['
t_RBRACKET = r'\]'
t_LBRACE = r'\{'
t_RBRACE = r'\}'
t_LANGLE = r'<'
t_RANGLE = r'>'
t_COMMA = r','
t_DOT = r'\.'
t_SEMI = r';'
t_STRING_LITERAL = string_literal
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_LBRACKET = r'\['
t_RBRACKET = r'\]'
t_LBRACE = r'\{'
t_RBRACE = r'\}'
t_LANGLE = r'<'
t_RANGLE = r'>'
t_COMMA = r','
t_DOT = r'\.'
t_SEMI = r';'
t_STRING_LITERAL = string_literal
# The following floating and integer constants are defined as
# functions to impose a strict order (otherwise, decimal
......
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Generates a syntax tree from a Mojo IDL file."""
import os.path
......@@ -17,7 +16,6 @@ from ..error import Error
from . import ast
from .lexer import Lexer
_MAX_ORDINAL_VALUE = 0xffffffff
_MAX_ARRAY_SIZE = 0xffffffff
......@@ -26,14 +24,17 @@ class ParseError(Error):
"""Class for errors from the parser."""
def __init__(self, filename, message, lineno=None, snippet=None):
Error.__init__(self, filename, message, lineno=lineno,
addenda=([snippet] if snippet else None))
Error.__init__(
self,
filename,
message,
lineno=lineno,
addenda=([snippet] if snippet else None))
# We have methods which look like they could be functions:
# pylint: disable=R0201
class Parser(object):
def __init__(self, lexer, source, filename):
self.tokens = lexer.tokens
self.source = source
......@@ -65,23 +66,28 @@ class Parser(object):
def p_root_2(self, p):
"""root : root module"""
if p[1].module is not None:
raise ParseError(self.filename,
"Multiple \"module\" statements not allowed:",
p[2].lineno, snippet=self._GetSnippet(p[2].lineno))
raise ParseError(
self.filename,
"Multiple \"module\" statements not allowed:",
p[2].lineno,
snippet=self._GetSnippet(p[2].lineno))
if p[1].import_list.items or p[1].definition_list:
raise ParseError(
self.filename,
"\"module\" statements must precede imports and definitions:",
p[2].lineno, snippet=self._GetSnippet(p[2].lineno))
p[2].lineno,
snippet=self._GetSnippet(p[2].lineno))
p[0] = p[1]
p[0].module = p[2]
def p_root_3(self, p):
"""root : root import"""
if p[1].definition_list:
raise ParseError(self.filename,
"\"import\" statements must precede definitions:",
p[2].lineno, snippet=self._GetSnippet(p[2].lineno))
raise ParseError(
self.filename,
"\"import\" statements must precede definitions:",
p[2].lineno,
snippet=self._GetSnippet(p[2].lineno))
p[0] = p[1]
p[0].import_list.Append(p[2])
......@@ -94,8 +100,8 @@ class Parser(object):
"""import : attribute_section IMPORT STRING_LITERAL SEMI"""
# 'eval' the literal to strip the quotes.
# TODO(vtl): This eval is dubious. We should unquote/unescape ourselves.
p[0] = ast.Import(p[1], eval(p[3]), filename=self.filename,
lineno=p.lineno(2))
p[0] = ast.Import(
p[1], eval(p[3]), filename=self.filename, lineno=p.lineno(2))
def p_module(self, p):
"""module : attribute_section MODULE identifier_wrapped SEMI"""
......@@ -251,8 +257,8 @@ class Parser(object):
def p_parameter(self, p):
"""parameter : attribute_section typename NAME ordinal"""
p[0] = ast.Parameter(p[3], p[1], p[4], p[2],
filename=self.filename, lineno=p.lineno(3))
p[0] = ast.Parameter(
p[3], p[1], p[4], p[2], filename=self.filename, lineno=p.lineno(3))
def p_typename(self, p):
"""typename : nonnullable_typename QSTN
......@@ -307,16 +313,15 @@ class Parser(object):
if len(p) == 2:
p[0] = p[1]
else:
if p[3] not in ('data_pipe_consumer',
'data_pipe_producer',
'message_pipe',
'shared_buffer',
'platform'):
if p[3] not in ('data_pipe_consumer', 'data_pipe_producer',
'message_pipe', 'shared_buffer', 'platform'):
# Note: We don't enable tracking of line numbers for everything, so we
# can't use |p.lineno(3)|.
raise ParseError(self.filename, "Invalid handle type %r:" % p[3],
lineno=p.lineno(1),
snippet=self._GetSnippet(p.lineno(1)))
raise ParseError(
self.filename,
"Invalid handle type %r:" % p[3],
lineno=p.lineno(1),
snippet=self._GetSnippet(p.lineno(1)))
p[0] = "handle<" + p[3] + ">"
def p_array(self, p):
......@@ -327,9 +332,11 @@ class Parser(object):
"""fixed_array : ARRAY LANGLE typename COMMA INT_CONST_DEC RANGLE"""
value = int(p[5])
if value == 0 or value > _MAX_ARRAY_SIZE:
raise ParseError(self.filename, "Fixed array size %d invalid:" % value,
lineno=p.lineno(5),
snippet=self._GetSnippet(p.lineno(5)))
raise ParseError(
self.filename,
"Fixed array size %d invalid:" % value,
lineno=p.lineno(5),
snippet=self._GetSnippet(p.lineno(5)))
p[0] = p[3] + "[" + p[5] + "]"
def p_associative_array(self, p):
......@@ -352,9 +359,11 @@ class Parser(object):
"""ordinal : ORDINAL"""
value = int(p[1][1:])
if value > _MAX_ORDINAL_VALUE:
raise ParseError(self.filename, "Ordinal value %d too large:" % value,
lineno=p.lineno(1),
snippet=self._GetSnippet(p.lineno(1)))
raise ParseError(
self.filename,
"Ordinal value %d too large:" % value,
lineno=p.lineno(1),
snippet=self._GetSnippet(p.lineno(1)))
p[0] = ast.Ordinal(value, filename=self.filename, lineno=p.lineno(1))
def p_enum_1(self, p):
......@@ -362,13 +371,13 @@ class Parser(object):
RBRACE SEMI
| attribute_section ENUM NAME LBRACE nonempty_enum_value_list \
COMMA RBRACE SEMI"""
p[0] = ast.Enum(p[3], p[1], p[5], filename=self.filename,
lineno=p.lineno(2))
p[0] = ast.Enum(
p[3], p[1], p[5], filename=self.filename, lineno=p.lineno(2))
def p_enum_2(self, p):
"""enum : attribute_section ENUM NAME SEMI"""
p[0] = ast.Enum(p[3], p[1], None, filename=self.filename,
lineno=p.lineno(2))
p[0] = ast.Enum(
p[3], p[1], None, filename=self.filename, lineno=p.lineno(2))
def p_enum_value_list_1(self, p):
"""enum_value_list : """
......@@ -391,8 +400,12 @@ class Parser(object):
"""enum_value : attribute_section NAME
| attribute_section NAME EQUALS int
| attribute_section NAME EQUALS identifier_wrapped"""
p[0] = ast.EnumValue(p[2], p[1], p[4] if len(p) == 5 else None,
filename=self.filename, lineno=p.lineno(2))
p[0] = ast.EnumValue(
p[2],
p[1],
p[4] if len(p) == 5 else None,
filename=self.filename,
lineno=p.lineno(2))
def p_const(self, p):
"""const : attribute_section CONST typename NAME EQUALS constant SEMI"""
......@@ -446,8 +459,11 @@ class Parser(object):
# TODO(vtl): Can we figure out what's missing?
raise ParseError(self.filename, "Unexpected end of file")
raise ParseError(self.filename, "Unexpected %r:" % e.value, lineno=e.lineno,
snippet=self._GetSnippet(e.lineno))
raise ParseError(
self.filename,
"Unexpected %r:" % e.value,
lineno=e.lineno,
snippet=self._GetSnippet(e.lineno))
def _GetSnippet(self, lineno):
return self.source.split('\n')[lineno - 1]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment