dom/bindings/Codegen.py
author Boris Zbarsky <bzbarsky@mit.edu>
Thu, 26 Jan 2012 17:23:31 +0100
changeset 85149 4119ff5bd1104150455174319f6f1edba3d41c8f
parent 85148 fdee219a75502a61e28f8d2990ec4d91385e4dbd
child 85150 cc2e300dab5b4a3beea5b95d2e9b32337cb032a0
permissions -rw-r--r--
Implement prototype setup infrastructure.

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

# Common codegen classes.

class CodegenThing():
    """
    Abstract base case for things that spit out code within a class.
    """
    def __init__(self, implementation):
        self.implementation = implementation
    def declare(self):
        """Produce code for a header file."""
        return "" # Override me!
    def implement(self):
        """Produce code for a cpp file."""
        return "" # Override me!

class Argument():
    def __init__(self, argType, name):
        self.argType = argType
        self.name = name
    def __str__(self):
        return self.argType + ' ' + self.name

class AbstractMethod(CodegenThing):
    def __init__(self, implementation, name, returnType, args):
        CodegenThing.__init__(self, implementation)
        self.name = name
        self.returnType = returnType
        self.args = args
    def declare(self):
        return "%s %s(%s);\n" % (self.returnType, self.name, ', '.join(self.args))
    def define(self):
        return self.definition_prologue() + self.definition_body() + self.definition_epilogue()
    def definition_prologue(self):
        return "%s\n%s(%s)\n{\n"
    def definition_epilogue(self):
        return "\n}\n"
    def definition_body(self):
        return "" # Override me!

class InstallMethod(AbstractMethod):
    def __init__(self, implementation):
        args = [Argument('JSContext*', 'aCx'), Argument('JSObject*', 'aGlobal')]
        AbstractMethod.__init__(self, implementation, 'Install', 'bool', args)
    def definition_body(self):
        return 'return false;\n'

class DOMClassImplementation():
    def __init__(self, domClass, implConf):
        self.domClass = domClass
        self.nativeClass = implConf['nativeClass']
        self.workers = implConf.get('workers', False)
        if self.workers:
            self.name = domClass.name + '_workers'
        else:
            self.name = domClass.name
        self.nativeIsISupports = not self.workers

class DOMClass():
    def __init__(self, classConf, interface):
        self.name = classConf['name']
        self.implementations = [DOMClassImplementation(self, implConf) for implConf in classConf['implementations']]

        # Build the interface chain.
        self.interfaceChain = [self.name]
        parent = interface.parent
        while parent:
            self.interfaceChain.insert(0, parent.identifier.name)
            parent = parent.parent
        self.interface = interface

class Configuration:
    def __init__(self, filename, parseData):
        self.configFile = {}
        execfile(filename, self.configFile)

        # We need dom_classes.
        if 'dom_classes' not in self.configFile:
            raise UserError(filename + ": `dom_classes` was not defined.")

        # Build data structures for classes where we have parse data. We've
        # already filtered the parse data so that this does what we want.
        self.dom_classes = dict()
        for classConf in self.configFile['dom_classes']:
            name = classConf['name']
            if name not in parseData:
                continue
            self.dom_classes[name] = DOMClass(classConf, parseData[name])