Commit 63fd1386 authored by Hitoshi Yoshida's avatar Hitoshi Yoshida Committed by Commit Bot

IDL compiler: Implement Namespace

In current spec, namespaces do not have constants,
but to reduce the risk of bugs, we let Namespace.IR
have constants.


Bug: 839389
Change-Id: Ia78091e045eb92f92538ae7d7b0d530bf589c636
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1792400
Commit-Queue: Hitoshi Yoshida <peria@chromium.org>
Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#697927}
parent 298a9896
...@@ -16,6 +16,7 @@ from .ir_map import IRMap ...@@ -16,6 +16,7 @@ from .ir_map import IRMap
from .idl_type import IdlTypeFactory from .idl_type import IdlTypeFactory
from .interface import Interface from .interface import Interface
from .make_copy import make_copy from .make_copy import make_copy
from .namespace import Namespace
from .operation import OperationGroup from .operation import OperationGroup
from .reference import RefByIdFactory from .reference import RefByIdFactory
from .typedef import Typedef from .typedef import Typedef
...@@ -79,7 +80,7 @@ class IdlCompiler(object): ...@@ -79,7 +80,7 @@ class IdlCompiler(object):
# Merge partial definitions. # Merge partial definitions.
self._propagate_extattrs_per_idl_fragment() self._propagate_extattrs_per_idl_fragment()
self._merge_partial_interfaces() self._merge_partial_interface_likes()
self._merge_partial_dictionaries() self._merge_partial_dictionaries()
# Merge mixins. # Merge mixins.
self._merge_interface_mixins() self._merge_interface_mixins()
...@@ -183,18 +184,22 @@ class IdlCompiler(object): ...@@ -183,18 +184,22 @@ class IdlCompiler(object):
map(process_interface_like, old_irs) map(process_interface_like, old_irs)
def _merge_partial_interfaces(self): def _merge_partial_interface_likes(self):
old_interfaces = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE) irs = self._ir_map.irs_of_kinds(IRMap.IR.Kind.INTERFACE,
partial_interfaces = self._ir_map.find_by_kind( IRMap.IR.Kind.INTERFACE_MIXIN,
IRMap.IR.Kind.PARTIAL_INTERFACE) IRMap.IR.Kind.NAMESPACE)
old_mixins = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE_MIXIN) partial_irs = self._ir_map.irs_of_kinds(
partial_mixins = self._ir_map.find_by_kind( IRMap.IR.Kind.PARTIAL_INTERFACE,
IRMap.IR.Kind.PARTIAL_INTERFACE_MIXIN) IRMap.IR.Kind.PARTIAL_INTERFACE_MIXIN,
IRMap.IR.Kind.PARTIAL_NAMESPACE)
self._ir_map.move_to_new_phase() self._ir_map.move_to_new_phase()
self._merge_interfaces(old_interfaces, partial_interfaces) ir_sets_to_merge = [(ir, [
self._merge_interfaces(old_mixins, partial_mixins) partial_ir for partial_ir in partial_irs
if partial_ir.identifier == ir.identifier
]) for ir in irs]
self._merge_interface_like_irs(ir_sets_to_merge)
def _merge_partial_dictionaries(self): def _merge_partial_dictionaries(self):
old_dictionaries = self._ir_map.find_by_kind(IRMap.IR.Kind.DICTIONARY) old_dictionaries = self._ir_map.find_by_kind(IRMap.IR.Kind.DICTIONARY)
...@@ -216,36 +221,30 @@ class IdlCompiler(object): ...@@ -216,36 +221,30 @@ class IdlCompiler(object):
def _merge_interface_mixins(self): def _merge_interface_mixins(self):
interfaces = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE) interfaces = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE)
interface_mixins = self._ir_map.find_by_kind( mixins = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE_MIXIN)
IRMap.IR.Kind.INTERFACE_MIXIN) includes = self._ir_map.find_by_kind(IRMap.IR.Kind.INCLUDES)
identifier_to_mixin_map = { ir_sets_to_merge = [(interface, [
identifier: [ mixins[include.mixin_identifier]
interface_mixins[include.mixin_identifier] for include in includes.get(identifier, [])
for include in includes ]) for identifier, interface in interfaces.iteritems()]
]
for identifier, includes in self._ir_map.find_by_kind(
IRMap.IR.Kind.INCLUDES).iteritems()
}
self._ir_map.move_to_new_phase() self._ir_map.move_to_new_phase()
self._merge_interfaces(interfaces, identifier_to_mixin_map) self._merge_interface_like_irs(ir_sets_to_merge)
def _merge_interfaces(self, old_interfaces, interfaces_to_be_merged): def _merge_interface_like_irs(self, old_irs_to_merge):
for identifier, old_interface in old_interfaces.iteritems(): for old_ir, irs_to_be_merged in old_irs_to_merge:
new_interface = make_copy(old_interface) new_ir = make_copy(old_ir)
for to_be_merged in interfaces_to_be_merged.get(identifier, []): for ir in irs_to_be_merged:
new_interface.add_components(to_be_merged.components) to_be_merged = make_copy(ir)
new_interface.debug_info.add_locations( new_ir.add_components(to_be_merged.components)
new_ir.debug_info.add_locations(
to_be_merged.debug_info.all_locations) to_be_merged.debug_info.all_locations)
new_interface.attributes.extend( new_ir.attributes.extend(to_be_merged.attributes)
make_copy(to_be_merged.attributes)) new_ir.constants.extend(to_be_merged.constants)
new_interface.constants.extend( new_ir.operations.extend(to_be_merged.operations)
make_copy(to_be_merged.constants)) self._ir_map.add(new_ir)
new_interface.operations.extend(
make_copy(to_be_merged.operations))
self._ir_map.add(new_interface)
def _process_interface_inheritances(self): def _process_interface_inheritances(self):
def is_own_member(member): def is_own_member(member):
...@@ -277,23 +276,22 @@ class IdlCompiler(object): ...@@ -277,23 +276,22 @@ class IdlCompiler(object):
self._ir_map.add(new_interface) self._ir_map.add(new_interface)
def _group_overloaded_functions(self): def _group_overloaded_functions(self):
old_interfaces = self._ir_map.irs_of_kind(IRMap.IR.Kind.INTERFACE) old_irs = self._ir_map.irs_of_kinds(IRMap.IR.Kind.INTERFACE,
IRMap.IR.Kind.NAMESPACE)
self._ir_map.move_to_new_phase() self._ir_map.move_to_new_phase()
for old_interface in old_interfaces: for old_ir in old_irs:
assert not old_interface.operation_groups assert not old_ir.operation_groups
new_interface = make_copy(old_interface) new_ir = make_copy(old_ir)
sort_key = lambda x: x.identifier sort_key = lambda x: x.identifier
sorted_operations = sorted(new_interface.operations, key=sort_key) new_ir.operation_groups = [
new_interface.operation_groups = [
OperationGroup.IR(operations=list(operations)) OperationGroup.IR(operations=list(operations))
for identifier, operations in itertools.groupby( for identifier, operations in itertools.groupby(
sorted_operations, key=sort_key) if identifier sorted(old_ir.operations, key=sort_key), key=sort_key)
if identifier
] ]
self._ir_map.add(new_ir)
self._ir_map.add(new_interface)
def _create_public_objects(self): def _create_public_objects(self):
"""Creates public representations of compiled objects.""" """Creates public representations of compiled objects."""
...@@ -303,6 +301,9 @@ class IdlCompiler(object): ...@@ -303,6 +301,9 @@ class IdlCompiler(object):
for ir in self._ir_map.irs_of_kind(IRMap.IR.Kind.INTERFACE_MIXIN): for ir in self._ir_map.irs_of_kind(IRMap.IR.Kind.INTERFACE_MIXIN):
self._db.register(DatabaseBody.Kind.INTERFACE_MIXIN, Interface(ir)) self._db.register(DatabaseBody.Kind.INTERFACE_MIXIN, Interface(ir))
for ir in self._ir_map.irs_of_kind(IRMap.IR.Kind.NAMESPACE):
self._db.register(DatabaseBody.Kind.NAMESPACE, Namespace(ir))
for ir in self._ir_map.irs_of_kind(IRMap.IR.Kind.DICTIONARY): for ir in self._ir_map.irs_of_kind(IRMap.IR.Kind.DICTIONARY):
self._db.register(DatabaseBody.Kind.DICTIONARY, Dictionary(ir)) self._db.register(DatabaseBody.Kind.DICTIONARY, Dictionary(ir))
......
...@@ -150,10 +150,32 @@ class _IRBuilder(object): ...@@ -150,10 +150,32 @@ class _IRBuilder(object):
debug_info=self._build_debug_info(node)) debug_info=self._build_debug_info(node))
def _build_namespace(self, node): def _build_namespace(self, node):
# TODO(peria): Build members and register them in |namespace| child_nodes = list(node.GetChildren())
extended_attributes = self._take_extended_attributes(child_nodes)
members = map(self._build_interface_or_namespace_member, child_nodes)
attributes = []
constants = []
operations = []
for member in members:
if isinstance(member, Attribute.IR):
member.is_static = True
attributes.append(member)
elif isinstance(member, Constant.IR):
constants.append(member)
elif isinstance(member, Operation.IR):
member.is_static = True
operations.append(member)
else:
assert False
return Namespace.IR( return Namespace.IR(
identifier=Identifier(node.GetName()), identifier=Identifier(node.GetName()),
is_partial=bool(node.GetProperty('PARTIAL')), is_partial=bool(node.GetProperty('PARTIAL')),
attributes=attributes,
constants=constants,
operations=operations,
extended_attributes=extended_attributes,
component=self._component, component=self._component,
debug_info=self._build_debug_info(node)) debug_info=self._build_debug_info(node))
......
...@@ -2,58 +2,112 @@ ...@@ -2,58 +2,112 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
import exceptions from .attribute import Attribute
from .code_generator_info import CodeGeneratorInfo
from .composition_parts import WithCodeGeneratorInfo from .composition_parts import WithCodeGeneratorInfo
from .composition_parts import WithComponent from .composition_parts import WithComponent
from .composition_parts import WithDebugInfo from .composition_parts import WithDebugInfo
from .composition_parts import WithExposure
from .composition_parts import WithExtendedAttributes from .composition_parts import WithExtendedAttributes
from .composition_parts import WithIdentifier from .constant import Constant
from .exposure import Exposure
from .ir_map import IRMap from .ir_map import IRMap
from .make_copy import make_copy
from .operation import Operation
from .operation import OperationGroup
from .user_defined_type import UserDefinedType
class Namespace(WithIdentifier, WithExtendedAttributes, WithCodeGeneratorInfo, class Namespace(UserDefinedType, WithExtendedAttributes, WithCodeGeneratorInfo,
WithComponent, WithDebugInfo): WithExposure, WithComponent, WithDebugInfo):
"""https://heycam.github.io/webidl/#idl-namespaces""" """https://heycam.github.io/webidl/#idl-namespaces"""
class IR(IRMap.IR, WithExtendedAttributes, WithCodeGeneratorInfo, class IR(IRMap.IR, WithExtendedAttributes, WithCodeGeneratorInfo,
WithComponent, WithDebugInfo): WithExposure, WithComponent, WithDebugInfo):
def __init__(self, def __init__(self,
identifier, identifier,
is_partial, is_partial,
attributes=None,
constants=None,
operations=None,
extended_attributes=None, extended_attributes=None,
code_generator_info=None,
component=None, component=None,
debug_info=None): debug_info=None):
assert isinstance(is_partial, bool)
assert attributes is None or isinstance(attributes, (list, tuple))
assert constants is None or isinstance(constants, (list, tuple))
assert operations is None or isinstance(operations, (list, tuple))
attributes = attributes or []
constants = constants or []
operations = operations or []
assert all(
isinstance(attribute, Attribute.IR) and attribute.is_readonly
and attribute.is_static for attribute in attributes)
assert all(
isinstance(constant, Constant.IR) for constant in constants)
assert all(
isinstance(operation, Operation.IR) and operation.identifier
and operation.is_static for operation in operations)
kind = (IRMap.IR.Kind.PARTIAL_NAMESPACE kind = (IRMap.IR.Kind.PARTIAL_NAMESPACE
if is_partial else IRMap.IR.Kind.NAMESPACE) if is_partial else IRMap.IR.Kind.NAMESPACE)
IRMap.IR.__init__(self, identifier=identifier, kind=kind) IRMap.IR.__init__(self, identifier=identifier, kind=kind)
WithExtendedAttributes.__init__(self, extended_attributes) WithExtendedAttributes.__init__(self, extended_attributes)
WithCodeGeneratorInfo.__init__(self, code_generator_info) WithCodeGeneratorInfo.__init__(self)
WithComponent.__init__(self, component) WithExposure.__init__(self)
WithComponent.__init__(self, component=component)
WithDebugInfo.__init__(self, debug_info) WithDebugInfo.__init__(self, debug_info)
self.is_partial = is_partial
self.attributes = list(attributes)
self.constants = list(constants)
self.operations = list(operations)
self.operation_groups = []
def __init__(self, ir):
assert isinstance(ir, Namespace.IR)
assert not ir.is_partial
ir = make_copy(ir)
UserDefinedType.__init__(self, ir.identifier)
WithExtendedAttributes.__init__(self, ir.extended_attributes)
WithCodeGeneratorInfo.__init__(
self, CodeGeneratorInfo(ir.code_generator_info))
WithExposure.__init__(self, Exposure(ir.exposure))
WithComponent.__init__(self, components=ir.components)
WithDebugInfo.__init__(self, ir.debug_info)
self._attributes = tuple([
Attribute(attribute_ir, owner=self)
for attribute_ir in ir.attributes
])
self._constants = tuple([
Constant(constant_ir, owner=self) for constant_ir in ir.constants
])
self._operations = tuple([
Operation(operation_ir, owner=self)
for operation_ir in ir.operations
])
self._operation_groups = tuple([
OperationGroup(
operation_group_ir,
filter(lambda x: x.identifier == operation_group_ir.identifier,
self._operations),
owner=self) for operation_group_ir in ir.operation_groups
])
@property @property
def attributes(self): def attributes(self):
""" """Returns attributes."""
Returns a list of attributes. return self._attributes
@return tuple(Attribute)
"""
raise exceptions.NotImplementedError()
@property @property
def operation_groups(self): def operations(self):
""" """Returns operations."""
Returns a list of OperationGroup. Each OperationGroup may have an operation return self._operations
or a set of overloaded operations.
@return tuple(OperationGroup)
"""
raise exceptions.NotImplementedError()
@property @property
def constants(self): def operation_groups(self):
""" """Returns a list of OperationGroups."""
Returns a list of constants. return self._operation_groups
@return tuple(Constant)
"""
raise exceptions.NotImplementedError()
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