aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/script/dom/bindings/codegen/CodegenRust.py
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2013-07-11 01:22:00 -0400
committerJosh Matthews <josh@joshmatthews.net>2013-07-12 14:06:23 -0400
commit4f24ef161973419cf32256ae1aee627cddb9c2c6 (patch)
treec92e54beddc7ad54e318be2f1f02d94e0a1be0ed /src/components/script/dom/bindings/codegen/CodegenRust.py
parent65f9aefb78791467fcd54971e0296c520e23d641 (diff)
downloadservo-4f24ef161973419cf32256ae1aee627cddb9c2c6.tar.gz
servo-4f24ef161973419cf32256ae1aee627cddb9c2c6.zip
DOM bindings: Autogenerate list of prototypes and binding registration goop.
Diffstat (limited to 'src/components/script/dom/bindings/codegen/CodegenRust.py')
-rw-r--r--src/components/script/dom/bindings/codegen/CodegenRust.py194
1 files changed, 176 insertions, 18 deletions
diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py
index e82c4167485..b4b418ff15d 100644
--- a/src/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/src/components/script/dom/bindings/codegen/CodegenRust.py
@@ -95,8 +95,8 @@ class CastableObjectUnwrapper():
self.substitution = { "type" : descriptor.nativeType,
"depth": descriptor.interface.inheritanceDepth(),
- "prototype": "prototypes::id::" + descriptor.name,
- "protoID" : "prototypes::id::" + descriptor.name + " as uint",
+ "prototype": "PrototypeList::id::" + descriptor.name,
+ "protoID" : "PrototypeList::id::" + descriptor.name + " as uint",
"source" : source,
"target" : target,
"codeOnFailure" : CGIndenter(CGGeneric(codeOnFailure), 4).define() }
@@ -942,7 +942,7 @@ for (uint32_t i = 0; i < length; ++i) {
else:
templateBody += (
"match unwrap_value::<" + typePtr + ">(&${val} as *JSVal, "
- "prototypes::id::%s, %d) {\n" % (descriptor.name, descriptor.interface.inheritanceDepth() if descriptor.concrete else 0) +
+ "PrototypeList::id::%s, %d) {\n" % (descriptor.name, descriptor.interface.inheritanceDepth() if descriptor.concrete else 0) +
" Err(()) => {")
templateBody += CGIndenter(onFailureBadType(failureCode,
descriptor.interface.identifier.name)).define()
@@ -2151,6 +2151,13 @@ class CGImports(CGWrapper):
CGWrapper.__init__(self, child,
declarePre=_useString(sorted(declareImports)))
+ @staticmethod
+ def getDeclarationFilename(decl):
+ # Use our local version of the header, not the exported one, so that
+ # test bindings, which don't export, will work correctly.
+ basename = os.path.basename(decl.filename())
+ return basename.replace('.webidl', 'Binding.rs')
+
class CGIfWrapper(CGWrapper):
def __init__(self, child, condition):
pre = CGWrapper(CGGeneric(condition), pre="if ", post=" {\n",
@@ -2178,12 +2185,12 @@ class CGNamespace(CGWrapper):
return ""
def DOMClass(descriptor):
- protoList = ['prototypes::id::' + proto for proto in descriptor.prototypeChain]
+ protoList = ['PrototypeList::id::' + proto for proto in descriptor.prototypeChain]
# Pad out the list to the right length with _ID_Count so we
# guarantee that all the lists are the same length. _ID_Count
# is never the ID of any prototype, so it's safe to use as
# padding.
- protoList.extend(['prototypes::id::_ID_Count'] * (descriptor.config.maxProtoChainLength - len(protoList)))
+ protoList.extend(['PrototypeList::id::_ID_Count'] * (descriptor.config.maxProtoChainLength - len(protoList)))
prototypeChainString = ', '.join(protoList)
nativeHooks = "0 as *NativePropertyHooks" if descriptor.workers else "&NativeHooks as *NativePropertyHooks"
return """DOMClass {
@@ -2382,7 +2389,7 @@ class CGAbstractMethod(CGThing):
template arguments, and the function will be templatized using those
arguments.
"""
- def __init__(self, descriptor, name, returnType, args, inline=False, alwaysInline=False, static=False, extern=False, pub=False, templateArgs=None):
+ def __init__(self, descriptor, name, returnType, args, inline=False, alwaysInline=False, static=False, extern=False, pub=False, templateArgs=None, unsafe=True):
CGThing.__init__(self)
self.descriptor = descriptor
self.name = name
@@ -2394,6 +2401,7 @@ class CGAbstractMethod(CGThing):
self.extern = extern
self.templateArgs = templateArgs
self.pub = pub;
+ self.unsafe = unsafe
def _argstring(self):
return ', '.join([str(a) for a in self.args])
def _template(self):
@@ -2421,6 +2429,10 @@ class CGAbstractMethod(CGThing):
return ' '.join(decorators) + maybeNewline
def _returnType(self):
return (" -> %s" % self.returnType) if self.returnType != "void" else ""
+ def _unsafe_open(self):
+ return "\n unsafe {" if self.unsafe else ""
+ def _unsafe_close(self):
+ return "\n }\n" if self.unsafe else ""
def declare(self):
if self.inline:
return self._define()
@@ -2433,10 +2445,10 @@ class CGAbstractMethod(CGThing):
def define(self):
return "" if self.inline else self._define()
def definition_prologue(self):
- return "%sfn %s%s(%s)%s {\n unsafe {" % (self._decorators(), self.name, self._template(),
- self._argstring(), self._returnType())
+ return "%sfn %s%s(%s)%s {%s" % (self._decorators(), self.name, self._template(),
+ self._argstring(), self._returnType(), self._unsafe_open())
def definition_epilogue(self):
- return "\n }\n}\n"
+ return "%s}\n" % self._unsafe_close()
def definition_body(self):
assert(False) # Override me!
@@ -2445,7 +2457,7 @@ def CreateBindingJSObject(descriptor, parent):
handler = """ //let cache = ptr::to_unsafe_ptr(aObject.get_wrappercache());
let script_context = task_from_context(aCx);
- let handler = (*script_context).dom_static.proxy_handlers.get(&(prototypes::id::%s as uint));
+ let handler = (*script_context).dom_static.proxy_handlers.get(&(PrototypeList::id::%s as uint));
""" % descriptor.name
create = handler + """ let obj = NewProxyObject(aCx, *handler,
ptr::to_unsafe_ptr(&RUST_PRIVATE_TO_JSVAL(squirrel_away(aObject) as *libc::c_void)),
@@ -2616,7 +2628,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
idsToInit.append(props.variableName(False))
if len(idsToInit) > 0:
setup = CGList([CGGeneric("let script_context = task_from_context(aCx);"),
- CGList([CGGeneric("let %s_ids_mut = (*script_context).dom_static.attribute_ids.get(&(prototypes::id::%s as uint));" % (varname, self.descriptor.name)) for varname in idsToInit], '\n')], '\n')
+ CGList([CGGeneric("let %s_ids_mut = (*script_context).dom_static.attribute_ids.get(&(PrototypeList::id::%s as uint));" % (varname, self.descriptor.name)) for varname in idsToInit], '\n')], '\n')
initIds = CGList(
[CGGeneric("!InitIds(aCx, %s, *%s_ids_mut)" % (varname, varname)) for
varname in idsToInit], ' ||\n')
@@ -2757,7 +2769,7 @@ class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
"""
def __init__(self, descriptor):
CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject",
- "prototypes::", pub=True)
+ "PrototypeList::", pub=True)
def definition_body(self):
return """
/* Get the interface prototype object for this class. This will create the
@@ -2837,12 +2849,12 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
getElementIfPresent: ptr::null(),
getPrototypeOf: ptr::null()
};
- (*script_context).dom_static.proxy_handlers.insert(prototypes::id::%s as uint,
+ (*script_context).dom_static.proxy_handlers.insert(PrototypeList::id::%s as uint,
CreateProxyHandler(ptr::to_unsafe_ptr(&traps), ptr::to_unsafe_ptr(&Class) as *libc::c_void));
""" % self.descriptor.name
else:
- body += """ (*script_context).dom_static.attribute_ids.insert(prototypes::id::%s as uint,
+ body += """ (*script_context).dom_static.attribute_ids.insert(PrototypeList::id::%s as uint,
vec::cast_to_mut(vec::from_slice(sAttributes_ids)));
""" % self.descriptor.name
body = "" #XXXjdm xray stuff isn't necessary yet
@@ -3336,7 +3348,7 @@ class CGMemberJITInfo(CGThing):
return ""
def defineJitInfo(self, infoName, opName, infallible):
- protoID = "prototypes::id::%s as u32" % self.descriptor.name
+ protoID = "PrototypeList::id::%s as u32" % self.descriptor.name
depth = self.descriptor.interface.inheritanceDepth()
failstr = "true" if infallible else "false"
return ("\n"
@@ -3436,7 +3448,7 @@ class CGXrayHelper(CGAbstractExternMethod):
methods = self.properties.methods
if methods.hasNonChromeOnly() or methods.hasChromeOnly():
methodArgs = "Some(vec::zip_slice(%(methods)s, *method_ids))" % varNames
- setup += "let method_ids = (*script_context).dom_static.method_ids.get(&(prototypes::id::ClientRect as uint));\n"
+ setup += "let method_ids = (*script_context).dom_static.method_ids.get(&(PrototypeList::id::ClientRect as uint));\n"
else:
methodArgs = "None"
methodArgs = CGGeneric(methodArgs)
@@ -3444,7 +3456,7 @@ class CGXrayHelper(CGAbstractExternMethod):
attrs = self.properties.attrs
if attrs.hasNonChromeOnly() or attrs.hasChromeOnly():
attrArgs = "Some(vec::zip_slice(%(attrs)s, *attr_ids))" % varNames
- setup += "let attr_ids = (*script_context).dom_static.attribute_ids.get(&(prototypes::id::ClientRect as uint));\n"
+ setup += "let attr_ids = (*script_context).dom_static.attribute_ids.get(&(PrototypeList::id::ClientRect as uint));\n"
else:
attrArgs = "None"
attrArgs = CGGeneric(attrArgs)
@@ -3452,7 +3464,7 @@ class CGXrayHelper(CGAbstractExternMethod):
consts = self.properties.consts
if consts.hasNonChromeOnly() or consts.hasChromeOnly():
constArgs = "Some(vec::zip_slice(%(consts)s, *const_ids))" % varNames
- setup += "let const_ids = (*script_context).dom_static.constant_ids.get(&(prototypes::id::ClientRect as uint));\n"
+ setup += "let const_ids = (*script_context).dom_static.constant_ids.get(&(PrototypeList::id::ClientRect as uint));\n"
else:
constArgs = "None"
constArgs = CGGeneric(constArgs)
@@ -3953,6 +3965,51 @@ class CGDescriptor(CGThing):
def define(self):
return self.cgRoot.define()
+class CGNamespacedEnum(CGThing):
+ def __init__(self, namespace, enumName, names, values, comment="", deriving=""):
+
+ if not values:
+ values = []
+
+ # Account for explicit enum values.
+ entries = []
+ for i in range(0, len(names)):
+ if len(values) > i and values[i] is not None:
+ entry = "%s = %s" % (names[i], values[i])
+ else:
+ entry = names[i]
+ entries.append(entry)
+
+ # Append a Count.
+ entries.append('_' + enumName + '_Count')
+
+ # Indent.
+ entries = [' ' + e for e in entries]
+
+ # Build the enum body.
+ enumstr = comment + 'pub enum %s {\n%s\n}\n' % (enumName, ',\n'.join(entries))
+ if deriving:
+ enumstr = ('#[deriving(%s)]\n' % deriving) + enumstr
+ curr = CGGeneric(enumstr)
+
+ # Add some whitespace padding.
+ curr = CGWrapper(curr, pre='\n',post='\n')
+
+ # Add the namespace.
+ curr = CGNamespace(namespace, curr, public=True)
+
+ # Add the typedef
+ #typedef = '\ntypedef %s::%s %s;\n\n' % (namespace, enumName, enumName)
+ #curr = CGList([curr, CGGeneric(typedef)])
+
+ # Save the result.
+ self.node = curr
+
+ def declare(self):
+ return self.node.declare()
+ def define(self):
+ return self.node.define()
+
class CGDictionary(CGThing):
def __init__(self, dictionary, descriptorProvider):
self.dictionary = dictionary;
@@ -4198,6 +4255,26 @@ class CGDictionary(CGThing):
deps.add(member.type.unroll().inner)
return deps
+class CGRegisterProtos(CGAbstractMethod):
+ def __init__(self, config):
+ CGAbstractMethod.__init__(self, None, 'Register', 'void',
+ [Argument('@mut Compartment', 'compartment')],
+ unsafe=False, pub=True)
+ self.config = config
+
+ def _registerProtos(self):
+ lines = [" assert!(codegen::%sBinding::DefineDOMInterface(\n"
+ " compartment.cx.ptr,\n"
+ " compartment.global_obj.ptr,\n"
+ " &mut unused));" % (desc.name)
+ for desc in self.config.getDescriptors(hasInterfaceObject=True,
+ isExternal=False,
+ workers=False,
+ register=True)]
+ return '\n'.join(lines) + '\n'
+ def definition_body(self):
+ return " let mut unused = false;\n" + self._registerProtos()
+
class CGBindingRoot(CGThing):
"""
Root codegen class for binding generation. Instantiate the class, and call
@@ -4308,3 +4385,84 @@ class CGBindingRoot(CGThing):
return stripTrailingWhitespace(self.root.declare())
def define(self):
return stripTrailingWhitespace(self.root.define())
+
+class GlobalGenRoots():
+ """
+ Roots for global codegen.
+
+ To generate code, call the method associated with the target, and then
+ call the appropriate define/declare method.
+ """
+
+ @staticmethod
+ def PrototypeList(config):
+
+ # Prototype ID enum.
+ protos = [d.name for d in config.getDescriptors(hasInterfacePrototypeObject=True)]
+
+ idEnum = CGNamespacedEnum('id', 'ID', protos, [0], deriving="Eq")
+ idEnum = CGList([idEnum])
+ idEnum.append(CGGeneric(declare="pub static MAX_PROTO_CHAIN_LENGTH: uint = " +
+ str(config.maxProtoChainLength) + ";\n\n"))
+
+ # Wrap all of that in our namespaces.
+ #idEnum = CGNamespace.build(['mozilla', 'dom', 'prototypes'],
+ # CGWrapper(idEnum, pre='\n'))
+ #idEnum = CGWrapper(idEnum, post='\n')
+
+ curr = CGList([idEnum])
+
+ # Constructor ID enum.
+ constructors = [d.name for d in config.getDescriptors(hasInterfaceObject=True,
+ hasInterfacePrototypeObject=False)]
+ idEnum = CGNamespacedEnum('id', 'ID', constructors, [0])
+
+ # Wrap all of that in our namespaces.
+ idEnum = CGNamespace.build(['mozilla', 'dom', 'constructors'],
+ CGWrapper(idEnum, pre='\n'))
+ idEnum = CGWrapper(idEnum, post='\n')
+
+ #XXXjdm Not sure what to do with the constructors right now
+ #curr.append(idEnum)
+
+ #traitsDecl = CGGeneric(declare="""
+#template <prototypes::ID PrototypeID>
+#struct PrototypeTraits;
+#
+#template <class ConcreteClass>
+#struct PrototypeIDMap;
+#""")
+
+ #traitsDecl = CGNamespace.build(['mozilla', 'dom'],
+ # CGWrapper(traitsDecl, post='\n'))
+
+ #curr.append(traitsDecl)
+
+ # Add the auto-generated comment.
+ curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
+
+ # Done.
+ return curr
+
+ @staticmethod
+ def RegisterBindings(config):
+
+ # TODO - Generate the methods we want
+ curr = CGRegisterProtos(config)
+
+ # Wrap all of that in our namespaces.
+ #curr = CGNamespace.build(['mozilla', 'dom'],
+ # CGWrapper(curr, post='\n'))
+ #curr = CGWrapper(curr, post='\n')
+
+ # Add the includes
+ defineIncludes = [CGImports.getDeclarationFilename(desc.interface)
+ for desc in config.getDescriptors(hasInterfaceObject=True,
+ workers=False,
+ register=True)]
+ curr = CGImports([], [], ['dom::bindings::codegen',
+ 'js::rust::Compartment'], defineIncludes, curr)
+
+ # Done.
+ return curr
+