Files
sdk/lib/html/scripts/systembase.py
T
vsm@google.com 79beeec1d4 Speed up fremontcut/dartdomgenerator
- Parse IDL in parallel
- Support calling fremontcut from dartdomgenerator to avoid reading database

This speeds up the whole go.sh by about 4x on my machine.  Looks like the remaining bottleneck is in the emitter.

Review URL: https://codereview.chromium.org//10987042

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@13038 260f80e4-7a28-3924-810f-c04153c831b5
2012-09-28 19:30:16 +00:00

197 lines
6.4 KiB
Python

#!/usr/bin/python
# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
"""This module provides base functionality for systems to generate
Dart APIs from the IDL database."""
import os
from generator import *
class System(object):
"""A System generates all the files for one implementation.
This is a base class for all the specific systems.
The life-cycle of a System is:
- construction (__init__)
- (ProcessInterface)* # for each IDL interface
"""
def __init__(self, options):
self._templates = options.templates
self._database = options.database
self._type_registry = options.type_registry
self._renamer = options.renamer
def ProcessInterface(self, interface):
"""Processes an interface that is not a callback function."""
pass
# Helper methods used by several systems.
def _BaseDefines(self, interface):
"""Returns a set of names (strings) for members defined in a base class.
"""
def WalkParentChain(interface):
if interface.parents:
# Only consider primary parent, secondary parents are not on the
# implementation class inheritance chain.
parent = interface.parents[0]
if IsDartCollectionType(parent.type.id):
return
if self._database.HasInterface(parent.type.id):
parent_interface = self._database.GetInterface(parent.type.id)
for attr in parent_interface.attributes:
result.add(attr.id)
for op in parent_interface.operations:
result.add(op.id)
WalkParentChain(parent_interface)
result = set()
WalkParentChain(interface)
return result
class BaseGenerator(object):
def __init__(self, database, type_registry, interface):
self._database = database
self._type_registry = type_registry
self._interface = interface
def Generate(self):
if 'Callback' in self._interface.ext_attrs:
handlers = [operation for operation in self._interface.operations
if operation.id == 'handleEvent']
info = AnalyzeOperation(self._interface, handlers)
self.GenerateCallback(info)
return
self.StartInterface()
self.AddMembers(self._interface)
self.AddSecondaryMembers(self._interface)
self.FinishInterface()
def GenerateCallback(self, info):
pass
def AddMembers(self, interface):
for const in sorted(interface.constants, ConstantOutputOrder):
self.AddConstant(const)
for attr in sorted(interface.attributes, ConstantOutputOrder):
if attr.type.id != 'EventListener':
self.AddAttribute(attr)
# The implementation should define an indexer if the interface directly
# extends List.
(element_type, requires_indexer) = ListImplementationInfo(
interface, self._database)
if element_type:
if requires_indexer:
self.AddIndexer(element_type)
else:
self.AmendIndexer(element_type)
# Group overloaded operations by id
operationsById = {}
for operation in interface.operations:
if operation.id not in operationsById:
operationsById[operation.id] = []
operationsById[operation.id].append(operation)
# Generate operations
for id in sorted(operationsById.keys()):
operations = operationsById[id]
info = AnalyzeOperation(interface, operations)
self.AddOperation(info)
def AddSecondaryMembers(self, interface):
# With multiple inheritance, attributes and operations of non-first
# interfaces need to be added. Sometimes the attribute or operation is
# defined in the current interface as well as a parent. In that case we
# avoid making a duplicate definition and pray that the signatures match.
secondary_parents = self._TransitiveSecondaryParents(interface)
for parent_interface in secondary_parents:
if isinstance(parent_interface, str): # IsDartCollectionType(parent_interface)
continue
for attr in sorted(parent_interface.attributes, ConstantOutputOrder):
if not FindMatchingAttribute(interface, attr):
self.AddSecondaryAttribute(parent_interface, attr)
# Group overloaded operations by id
operationsById = {}
for operation in parent_interface.operations:
if operation.id not in operationsById:
operationsById[operation.id] = []
operationsById[operation.id].append(operation)
# Generate operations
for id in sorted(operationsById.keys()):
if not any(op.id == id for op in interface.operations):
operations = operationsById[id]
info = AnalyzeOperation(interface, operations)
self.AddSecondaryOperation(parent_interface, info)
def AddConstant(self, constant):
pass
def AddAttribute(self, attribute):
pass
def AddIndexer(self, element_type):
pass
def AmendIndexer(self, element_type):
pass
def AddOperation(self, info):
pass
def AddSecondaryAttribute(self, interface, attribute):
pass
def AddSecondaryOperation(self, interface, info):
pass
def _TransitiveSecondaryParents(self, interface):
"""Returns a list of all non-primary parents.
The list contains the interface objects for interfaces defined in the
database, and the name for undefined interfaces.
"""
def walk(parents):
for parent in parents:
if IsDartCollectionType(parent.type.id):
result.append(parent.type.id)
continue
if self._database.HasInterface(parent.type.id):
parent_interface = self._database.GetInterface(parent.type.id)
result.append(parent_interface)
walk(parent_interface.parents)
result = []
if interface.parents:
parent = interface.parents[0]
if IsPureInterface(parent.type.id):
walk(interface.parents)
else:
walk(interface.parents[1:])
return result
def _TypeInfo(self, type_name):
return self._type_registry.TypeInfo(type_name)
def _DartType(self, type_name):
return self._type_registry.DartType(type_name)
class GeneratorOptions(object):
def __init__(self, templates, database, type_registry, renamer):
self.templates = templates
self.database = database
self.type_registry = type_registry
self.renamer = renamer
def IsReadOnly(attribute):
return attribute.is_read_only or 'Replaceable' in attribute.ext_attrs