Commit 94be217d authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

IDL compiler: Implement reference-resolution and dump-as-pickle

Resolves references to dictionaries (other references are
resolved to stubs for the time being), and dumps the database
object into a pickle file.

'pickle' only supports top-level classes, so DebugInfo.Location
is moved to a top-level class.  Also, reference-stubs are
temporarily necessary to pickle web_idl.Proxy instances.

Bug: 839389
Change-Id: Ifbdca0df8d34d1cad49bca854b32f0524aaff758
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1713066Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#679936}
parent 521f1235
......@@ -137,12 +137,8 @@ class WithComponent(object):
self._components.append(component)
class DebugInfo(object):
"""Provides information useful for debugging."""
class Location(object):
def __init__(self, filepath=None, line_number=None,
column_number=None):
class Location(object):
def __init__(self, filepath=None, line_number=None, column_number=None):
assert filepath is None or isinstance(filepath, str)
assert line_number is None or isinstance(line_number, int)
assert column_number is None or isinstance(column_number, int)
......@@ -159,7 +155,7 @@ class DebugInfo(object):
return text
def make_copy(self):
return DebugInfo.Location(
return Location(
filepath=self._filepath,
line_number=self._line_number,
column_number=self._column_number)
......@@ -176,11 +172,15 @@ class DebugInfo(object):
def column_number(self):
return self._column_number
class DebugInfo(object):
"""Provides information useful for debugging."""
def __init__(self, location=None, locations=None):
assert location is None or isinstance(location, DebugInfo.Location)
assert locations is None or (isinstance(
locations, (list, tuple)) and all(
isinstance(location, DebugInfo.Location)
assert location is None or isinstance(location, Location)
assert locations is None or (isinstance(locations, (list, tuple))
and all(
isinstance(location, Location)
for location in locations))
assert not (location and locations)
# The first entry is the primary location, e.g. location of non-partial
......@@ -189,17 +189,15 @@ class DebugInfo(object):
if locations:
self._locations = locations
else:
self._locations = [location or DebugInfo.Location()]
self._locations = [location or Location()]
def make_copy(self):
return DebugInfo(
locations=map(DebugInfo.Location.make_copy, self._locations))
return DebugInfo(locations=map(Location.make_copy, self._locations))
@property
def location(self):
"""
Returns the primary location, i.e. location of the main definition.
@return DebugInfo.Location
"""
return self._locations[0]
......@@ -208,13 +206,12 @@ class DebugInfo(object):
"""
Returns a list of locations of all related IDL definitions, including
partial definitions and mixins.
@return tuple(DebugInfo.Location)
"""
return tuple(self._locations)
def add_locations(self, locations):
assert isinstance(locations, (list, tuple)) and all(
isinstance(location, DebugInfo.Location) for location in locations)
isinstance(location, Location) for location in locations)
self._locations.extend(locations)
......
......@@ -62,7 +62,7 @@ class DatabaseBody(object):
self._defs[kind][user_defined_type.identifier] = user_defined_type
def find_by_identifier(self, identifier):
for defs_per_kind in self._defs:
for defs_per_kind in self._defs.itervalues():
if identifier in defs_per_kind:
return defs_per_kind[identifier]
raise KeyError(identifier)
......
......@@ -2,6 +2,9 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from .database import Database
from .database import DatabaseBody
from .dictionary import Dictionary
from .identifier_ir_map import IdentifierIRMap
from .idl_type import IdlTypeFactory
from .reference import RefByIdFactory
......@@ -49,27 +52,28 @@ class IdlCompiler(object):
self._ref_to_idl_type_factory = ref_to_idl_type_factory
self._ref_to_idl_def_factory = ref_to_idl_def_factory
self._idl_type_factory = idl_type_factory
self._db = DatabaseBody()
self._did_run = False # Run only once.
def build_database(self):
self._merge_partials()
self._merge_mixins()
self._resolve_inheritances()
self._resolve_exposures()
self._define_unions()
self._generate_database()
def _generate_database(self):
"""
Returns an IDL database based on this compiler.
"""
pass
assert not self._did_run
self._did_run = True
def _merge_partials(self):
"""
Merges partial definitions with corresponding non-partial definitions.
"""
# Merge partial definitions.
self._merge_partial_interfaces()
self._merge_partial_dictionaries()
# TODO(peria): Implement this. http:///crbug.com/839389
# Updates on IRs are finished. Create API objects.
self._create_public_objects()
# Resolve references.
self._resolve_references_to_idl_type()
self._resolve_references_to_idl_def()
return Database(self._db)
def _merge_partial_interfaces(self):
pass
def _merge_partial_dictionaries(self):
old_dictionaries = self._ir_map.find_by_kind(
......@@ -92,31 +96,27 @@ class IdlCompiler(object):
])
self._ir_map.add(new_dictionary)
def _merge_mixins(self):
"""
Merges mixins with interfaces that connected with includes statements.
"""
self._ir_map.move_to_new_phase()
# TODO(peria): Implement this. http:///crbug.com/839389
def _resolve_inheritances(self):
"""
Resolves inheritances and [Unforgeable]
"""
self._ir_map.move_to_new_phase()
# TODO(peria): Implement this. http:///crbug.com/839389
def _resolve_exposures(self):
"""
Links [Exposed] interfaces/namespaces with [Global] interfaces
"""
self._ir_map.move_to_new_phase()
# TODO(peria): Implement this. http:///crbug.com/839389
def _define_unions(self):
"""
Create a definition of union, that is unique in union types that have
same flattened-like members.
"""
self._ir_map.move_to_new_phase()
# TODO(peria): Implement this. http:///crbug.com/839389
def _create_public_objects(self):
"""Creates public representations of compiled objects."""
dictionary_irs = self._ir_map.find_by_kind(
IdentifierIRMap.IR.Kind.DICTIONARY)
for ir in dictionary_irs.itervalues():
self._db.register(DatabaseBody.Kind.DICTIONARY, Dictionary(ir))
def _resolve_references_to_idl_type(self):
def resolve(ref):
# Resolve to stubs for the time being.
ref.set_target_object(False)
self._ref_to_idl_type_factory.for_each(resolve)
def _resolve_references_to_idl_def(self):
def resolve(ref):
try:
ref.set_target_object(
self._db.find_by_identifier(ref.identifier))
except KeyError:
# Resolve to stubs for the time being.
ref.set_target_object(False)
self._ref_to_idl_def_factory.for_each(resolve)
......@@ -8,6 +8,7 @@ from .attribute import Attribute
from .callback_function import CallbackFunction
from .callback_interface import CallbackInterface
from .common import DebugInfo
from .common import Location
from .constant import Constant
from .dictionary import Dictionary
from .dictionary import DictionaryMember
......@@ -317,7 +318,7 @@ class _IRBuilder(object):
def _build_debug_info(self, node):
return DebugInfo(
location=DebugInfo.Location(
location=Location(
filepath=node.GetProperty('FILENAME'),
line_number=node.GetProperty('LINENO'),
column_number=node.GetProperty('POSITION')))
......
......@@ -17,12 +17,12 @@ class Proxy(object):
"""
Creates a new proxy to |target_object|.
Keyword arguments:
target_object -- The object to which attribute access is proxied. This
can be set later by set_target_object.
target_attrs -- None or list of attribute names to be proxied. If None,
all the attribute access is proxied.
target_attrs_with_priority -- None or list of attribute names to be
Args:
target_object: The object to which attribute access is proxied.
This can be set later by set_target_object.
target_attrs: None or list of attribute names to be proxied. If
None, all the attribute access is proxied.
target_attrs_with_priority: None or list of attribute names to be
unconditionally proxied with priority over attributes defined on
|self|. If None, no attribute has priority over own attributes.
"""
......@@ -36,7 +36,7 @@ class Proxy(object):
def __getattr__(self, attribute):
target_object = object.__getattribute__(self, '_target_object')
target_attrs = object.__getattribute__(self, '_target_attrs')
assert target_object
assert target_object is not None
if target_attrs is None or attribute in target_attrs:
return getattr(target_object, attribute)
raise AttributeError
......@@ -80,7 +80,7 @@ class Proxy(object):
@property
def target_object(self):
assert self._target_object
assert self._target_object is not None
return self._target_object
......@@ -151,4 +151,4 @@ class RefByIdFactory(object):
assert callable(callback)
self._is_frozen = True
for ref in self._references:
resolver(ref)
callback(ref)
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